Documentation menu

API errors

Every endpoint under https://litport.net/api/v1 (Tokens and usage, Packages, and Pay-per-GB) returns its errors in the JSON format on this page. Failures of a proxied connection itself use separate numeric proxy error codes, and the public free proxy API is not covered here.

Error envelope#

{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Authentication failed.",
    "requestId": "req_example",
    "docsUrl": "https://litport.net/docs/api/errors",
    "retryable": false
  }
}

The same request ID appears in the X-Request-ID header. Log it with the HTTP status and error code. Never log the Authorization header.

A 409 that carries a wait also adds nextChangeAt, an ISO-8601 UTC timestamp: CHANGE_LIMIT on a token's location or new IP.

retryable is always there, true or false. true means the same request, sent again unchanged after Retry-After (or nextChangeAt, when the error has one), can succeed and is safe to send again: nothing was done (RATE_LIMITED, CONCURRENT_CHANGE, CHANGE_LIMIT, ALLOWANCE_CONFLICT), or it is a 503 on a request that is safe to repeat. false means change something first: the request, the account, or the token. A 503 on a request that isn't safe to repeat is false too: read the current state before you decide (see Retry algorithm).

Status reference#

Status Codes Client action
400 INVALID_REQUEST_BODY, INVALID_LIMIT, INVALID_CURSOR, INVALID_TYPE, INVALID_STATUS, INVALID_PACKAGE_ID, INVALID_TOKEN_IDS, INVALID_TIME_RANGE, INVALID_GROUP_BY, INVALID_INCLUDE, INVALID_POOL, INVALID_LEVEL, INVALID_PARENT, GEO_NOT_ENABLED, GEO_LEVEL_UNSUPPORTED, INVALID_IP, IPV6_UNSUPPORTED, INVALID_LOCATION, INVALID_ROTATION, INVALID_LABEL, INVALID_EXTERNAL_REF, INVALID_REQUEST_ID, INVALID_ENABLED, INVALID_EXPIRY, INVALID_ALLOWANCE, FIELD_NOT_ALLOWED Correct the request. Do not retry it unchanged.
401 UNAUTHORIZED Supply a current API key using the Bearer scheme. The response does not reveal whether a key or user exists.
402 INSUFFICIENT_BALANCE Top up the balance, then send the request again. Only creating a proxy and switching one on need a balance.
403 ACCOUNT_BANNED Creating a proxy or switching one on isn't allowed while the account is blocked. Contact support.
404 TOKEN_NOT_FOUND, PACKAGE_NOT_FOUND Check the ID and ownership. The response does not disclose another user's token or package.
404 NOT_FOUND Correct the route; it does not exist.
405 METHOD_NOT_ALLOWED Use one of the methods in the Allow header.
409 NOT_SUPPORTED, PACKAGE_INACTIVE, CONCURRENT_CHANGE, LOCATION_UNAVAILABLE, NOT_IN_FALLBACK, CHANGE_LIMIT, ALLOWED_IPS_LIMIT_REACHED, TOKEN_LIMIT_REACHED, TOKEN_NOT_EDITABLE, ALLOWANCE_CONFLICT, POOL_REQUIRED_FOR_IP_AUTH See the matching detail below; CONCURRENT_CHANGE and ALLOWANCE_CONFLICT mean retry the same request, CHANGE_LIMIT means wait for the reported nextChangeAt and then retry; all three have retryable: true.
413 INVALID_REQUEST_BODY The body exceeds 4 KiB. Send a smaller one.
415 INVALID_CONTENT_TYPE Send Content-Type: application/json for a write with a body.
429 RATE_LIMITED Respect Retry-After and use jittered backoff. retryable is true.
503 SERVICE_UNAVAILABLE, TOKEN_DATA_INVALID, ALLOWED_IPS_UNAVAILABLE Respect Retry-After. Retry with bounded backoff when retryable is true, then contact support with the request ID.

Retry algorithm#

Retry automatically only when retryable is true: wait for Retry-After (and for nextChangeAt, when the error has one), add jitter, and send the same request again. Cap attempts and make the total retry budget visible to the caller. When retryable is false, change something first, or, after an unclear failure of a request that isn't safe to repeat (see below), read the current state before you decide.

Every write in this API is safe to repeat except new-ip, POST /tokens without an externalRef, POST /tokens/{tokenId}/credentials without a requestId, PUT /tokens/{tokenId}/location with {"random": true}, and the two POSTs of the Support API (POST /support/conversations and POST /support/conversations/{conversationId}/messages). Any other write that gets a 409 CONCURRENT_CHANGE or an ambiguous response (timeout, lost response, 503) can simply be sent again, because the latest write always wins and every other write is a no-op when it is already applied. A 503 on a request that isn't safe to repeat has retryable: false, because the work may have been done before the failure.

For new-ip on a static token, an ambiguous result means reading GET /tokens/{tokenId}/location first and retrying only when nextChangeAt is not already later than the current time. A blind repeat inside the week only returns 409 CHANGE_LIMIT.

A create is safe to repeat when it carries an externalRef: the repeat returns the proxy that exists. Without one, a repeat can create a second proxy. A reissue is safe to repeat when it carries a requestId: the repeat returns the credentials the first call issued. Without one, a repeat issues another pair. See Create and manage proxies.

On a rotating token, new-ip can't be confirmed from GET /tokens/{tokenId}/location: its canChangeNow and nextChangeAt are about the location and say nothing about the wait between new IPs. Sending it again after Retry-After is harmless; it just gives another new IP. A 409 CHANGE_LIMIT right after a lost response does not prove the change happened, because a 409 LOCATION_UNAVAILABLE answer also uses up the wait.

PUT /tokens/{tokenId}/location with {"random": true} picks a new location each time, so a repeat moves the proxy again wherever no wait applies. After a lost response, read GET /tokens/{tokenId}/location first and send it again only if the proxy isn't where you want it. The Support API's two POSTs have no idempotency key, and a 503 can come after the message was stored: read the conversation before you send the message again.

Error code details#

Invalid request body#

400 when the body fails to parse as JSON or fails an endpoint's own shape check (for example, PUT /tokens/{tokenId}/rotation needs exactly {"intervalSec": <integer>}). On POST /tokens, PATCH /tokens/{tokenId} and POST /tokens/{tokenId}/credentials the body must be a JSON object holding only the fields that call takes, and a PATCH needs at least one. 413 when the body exceeds 4 KiB.

Invalid content type#

INVALID_CONTENT_TYPE means a write with a body was sent without Content-Type: application/json.

Invalid limit#

INVALID_LIMIT means limit is not an integer from 1 through 100.

Invalid cursor#

INVALID_CURSOR means the opaque cursor is malformed, edited, cannot be authenticated, or was issued for a different endpoint. Restart pagination without a cursor.

Invalid type#

INVALID_TYPE means type on GET /tokens is not unlimited or ppg.

Invalid status#

INVALID_STATUS means status on GET /tokens is not active, expired, or disabled.

Invalid token IDs#

INVALID_TOKEN_IDS means tokenIds on GET /usage is not a list of positive proxy IDs, or names more than 100.

Invalid package ID#

INVALID_PACKAGE_ID means the packageId filter on GET /tokens is not a positive integer. A packageId in a URL path is never a 400: an unknown or foreign one is 404 PACKAGE_NOT_FOUND.

Invalid time range#

INVALID_TIME_RANGE means a timestamp is not canonical UTC, from is not before to, or the requested span is too large.

Invalid group by#

INVALID_GROUP_BY means groupBy is not hour, day, or month.

Invalid include#

INVALID_INCLUDE means the requested expansion is incompatible with the token or grouping; charge components require a PPG token and hourly buckets.

Invalid pool#

INVALID_POOL means pool on GET /pay-per-gb/geo, POST /tokens, or PATCH /tokens/{tokenId} is missing where it is required, empty, or contains an auth key that does not resolve to a customer-selectable pool.

Invalid level#

INVALID_LEVEL means level is not one of the values that endpoint accepts: region/city for a token's location options, or country/region/city for pay-per-GB geo.

Invalid parent#

INVALID_PARENT means a required parent geography is missing: a token's location/options?level=city needs region; GET /pay-per-gb/geo needs country for level=region and for level=city.

Geo not enabled#

GEO_NOT_ENABLED means a requested pool has geo targeting switched off.

Geo level unsupported#

GEO_LEVEL_UNSUPPORTED means a requested pool does not support the requested level. Check the pool's geoLevels in Pay-per-GB.

Invalid IP#

INVALID_IP means the supplied address is not an exact public IPv4 literal.

IPv6 unsupported#

IPV6_UNSUPPORTED means an IPv6 address was sent to a package allowed-IP write; contact support.

Invalid location#

INVALID_LOCATION means the requested region, city, or carrier is not a value this token can use, or country was sent as something other than "us".

Invalid rotation#

INVALID_ROTATION means intervalSec on PUT /tokens/{tokenId}/rotation is not one of the token's listed options.

Invalid label#

INVALID_LABEL means label is not text of at most 255 characters, or null to clear it.

Invalid external ref#

INVALID_EXTERNAL_REF means externalRef is not 1 to 128 printable characters.

Invalid request ID#

INVALID_REQUEST_ID means requestId on POST /tokens/{tokenId}/credentials is not 1 to 64 characters of letters, digits, underscore, or hyphen.

Invalid enabled#

INVALID_ENABLED means enabled is not true or false.

Invalid expiry#

INVALID_EXPIRY means expiresAt is not an ISO 8601 date-time with a zone, or a date, that is still ahead, or null.

Invalid allowance#

INVALID_ALLOWANCE means allowanceBytes is not an integer of at least 1 (bytes), or null to remove the cap.

Field not allowed#

FIELD_NOT_ALLOWED means PATCH /tokens/{tokenId} sent a package's proxy a field other than label. A package's proxies are switched on and off by their package.

Unauthorized#

UNAUTHORIZED covers missing, malformed, unknown, rotated, and ownerless keys without revealing which condition occurred.

Token not found#

TOKEN_NOT_FOUND covers a missing, unowned, or unparseable tokenId on any token route. The response is identical in every case, so it never discloses another user's token.

Package not found#

PACKAGE_NOT_FOUND covers a missing, unowned, or unparseable packageId on any package route, including a package's allowed IPs.

Not found#

NOT_FOUND means the requested /api/v1 route does not exist.

Method not allowed#

METHOD_NOT_ALLOWED means a known endpoint received an unsupported method. The response includes its supported methods in Allow.

Not supported#

NOT_SUPPORTED means this token has no such control: its location can't be changed, its rotation interval can't be changed, or (new-ip) it is not a datacenter or ISP proxy. A Multi-location token's rotation interval always answers NOT_SUPPORTED, because the phone the proxy is on sets it. DELETE /tokens/{tokenId} on a package's proxy answers it too: only pay-per-GB proxies can be deleted.

Insufficient balance#

INSUFFICIENT_BALANCE is 402. Creating a proxy and switching one on need a positive balance. Everything else works with an empty balance: switching off, relabelling, changing the expiry or the cap, reissuing credentials, and deleting.

Account banned#

ACCOUNT_BANNED is 403. An account that is blocked can't create a proxy or switch one on. Switching off, reissuing credentials, and deleting still work. Contact support.

Token limit reached#

TOKEN_LIMIT_REACHED means the account already has the most pay-per-GB proxies it may hold. Delete one you no longer use, or contact support to raise the limit.

Token not editable#

TOKEN_NOT_EDITABLE means the proxy can no longer be edited, for example because it was deleted while the write ran. Nothing changed. Read the proxy to see where it stands.

Allowance conflict#

ALLOWANCE_CONFLICT means the traffic cap could not be saved. Nothing changed. Send the same request again.

Pool required for IP auth#

POOL_REQUIRED_FOR_IP_AUTH means pool: null was sent for a proxy that signs in by allowed IP. That proxy keeps one pool.

Package inactive#

PACKAGE_INACTIVE means the token's or package's paid period is not currently active.

Concurrent change#

CONCURRENT_CHANGE means another write to the same token or package landed at the same moment. Retry the same request.

Location unavailable#

LOCATION_UNAVAILABLE means the requested location currently has no usable IP or working device. Nothing changed.

Not in fallback#

NOT_IN_FALLBACK is the answer of POST /tokens/{tokenId}/location/return when the token isn't outside its saved location, so there is nothing to move back. A repeat of a request that already worked lands here and gives no second IP. Nothing changed.

Change limit#

CHANGE_LIMIT means a change or replacement allowance is already used: once a week for a static datacenter/ISP new IP or location change, once per 48 hours for a standard US Shared Mobile location change. For a new IP on a rotating datacenter/ISP token the wait is the shortest value in the token's rotation.options, counted from the last request. The error carries nextChangeAt and a matching Retry-After.

Allowed IPs limit reached#

ALLOWED_IPS_LIMIT_REACHED means the package's allowed-IP list is already at its limit (1 or 50). Contact support to raise it.

Rate limited#

RATE_LIMITED means the API key (for GET /usage, its own limit of 10 requests per 60 seconds), for an allowed-IP write the package, or for POST /tokens the account (its limit on creating new proxies each minute, shared by all its keys and the dashboard), exhausted its current window. Nothing was done. Respect Retry-After; retryable is true.

Service unavailable#

SERVICE_UNAVAILABLE means an API dependency is temporarily unavailable. Respect Retry-After. retryable is false when the request isn't safe to repeat; see Retry algorithm.

Token data invalid#

TOKEN_DATA_INVALID means a token's stored metadata is temporarily unreadable. Retry later, then report the request ID.

Allowed IPs unavailable#

ALLOWED_IPS_UNAVAILABLE means allowed-IP storage, configuration, or port allocation is unavailable, including a package temporarily out of assignable ports.

Authentication failures#

The API deliberately returns the same 401 envelope for malformed, unknown, rotated, and ownerless keys. Create or rotate an API key in Settings. A rotation immediately invalidates the previous active key.