Server Responses
The Kibot API uses HTTP status codes for both success and failure, with a small extension set in the 400 range that overloads the standard meanings to communicate Kibot-specific conditions like "wrong symbol", "data not available for that period", and "rate limit exceeded". This article catalogues every documented code, explains the gotcha around 403 Login Failed being reused for rate-limit trips, and covers the gzip/deflate compression negotiation that callers should always opt into for tick and intraday responses.
Status codes
Successful requests
| Code | Meaning |
|---|---|
200 OK |
The request succeeded. Body carries the payload (CSV bars, TAB-separated adjustments, snapshot rows, or a status banner). |
200 is the only success code. Any non-200 status, including 404, is either an error or a Kibot-specific signal documented below.
Client errors (4xx)
| Code | Meaning | What it usually means in practice |
|---|---|---|
400 Bad Request |
The request was malformed | Missing required parameter (e.g. action), or a typo in a parameter name |
401 Not Logged In |
The request requires authentication | Session expired (20-minute idle timeout) or never established; re-login and retry |
402 Unauthorized |
Logged in, but not entitled to this symbol | Symbol is not in any of the account's purchased packages |
403 Login Failed |
Username or password is invalid, or rate limit tripped | Bad credentials on login; or 40 concurrent / 50-per-500ms ceiling hit on a data call (per support, see Data updates) |
404 Symbol Not Found |
The server has no record of this symbol | Typo in the symbol; or the wrong &type= for the instrument class (e.g. forgetting &type=futures for a futures ticker) |
405 Data Not Found |
The symbol exists but no data is available for the requested period | Date range falls before the symbol's history starts, or after it stopped trading; also seen when the whole requested window lies past the account's update-plan cutoff (see Data updates); also returned by adjustments when no splits/dividends are present in the requested window |
The most consequential reuse to be aware of is 403 Login Failed. The same code is returned for actual auth failures and for rate-limit trips. Robust callers should not treat 403 after a successful login as an auth problem, it is almost always the throttle. Detail in API authentication.
The most consequential non-error response is 404 Not Found from ?action=adjustments. It is the documented "nothing has happened to this symbol since your cursor date" signal that drives the incremental-update pattern, treat it as a normal control-flow branch, not an exception.
Server errors (5xx)
The docs do not enumerate specific 5xx codes, but Kibot's response-codes page describes the 4xx set as "generic responses from the server. You can use the codes below in your applications to determine the status of the request you sent to the server." Standard practice for any 5xx response is to back off and retry, these typically correlate with the kind of maintenance window that the status command is meant to detect.
Compression
The Kibot API supports gzip and deflate response compression and uses the standard HTTP Accept-Encoding negotiation. The compression docs describe the contract succinctly: "Our servers use the Accept-Encoding HTTP header to determine whether to compress historical data sent to the client application. The default and recommended compression algorithm is gzip" (per the compression docs).
Client side
Send the standard request header any modern HTTP library sends by default:
Accept-Encoding: gzip,deflate
Most clients then decompress transparently. In .NET's HttpWebRequest, set AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip and the framework handles the unwrap (see the official sample in API client examples). Python's requests decompresses automatically. Rust's reqwest requires gzip(true) on the client builder. Go's net/http decompresses transparently when the request omits Accept-Encoding and the server responds with gzip; if the request explicitly sends Accept-Encoding: gzip, the caller is responsible for decompression.
Why it matters
For tick and intraday responses, gzip typically compresses the body by 5–10×. A 100 MB raw tick file lands as 10–20 MB on the wire, which on a typical broadband link is the difference between a 5-minute and a 30-second download. Daily and weekly responses are small enough that the savings are negligible per call but still worth the constant overhead.
The server only compresses when the client opts in via the header. A request without Accept-Encoding gets the raw uncompressed body, which is correct behaviour by HTTP spec but easy to leave money on the table.
Server side
Kibot's docs note that the response includes a Content-Encoding: gzip header when compression is applied. Callers that bypass their library's default decompression and read raw bytes off the socket need to check this header and run the body through their language's gzip module before parsing.
Practical patterns
Differentiate 403 Login Failed causes
Track request rate in the client. If a 403 arrives within the first second of a session, it is almost certainly bad credentials. If it arrives mid-stream after dozens of successful requests, it is almost certainly the rate limiter. The remedy is different, fix credentials vs. back off and retry, so guessing wrong wastes time.
Treat 404 from adjustments as success
Wrap the adjustments call in a try/except that catches 404 specifically and returns "no changes" rather than re-raising. Every other endpoint treats 404 as a real error (symbol not found); adjustments overloads it to mean "no rows in your window".
Always send Accept-Encoding
Even on small responses where the savings are marginal, the constant cost of advertising gzip support is zero. Most HTTP libraries do this by default, verify yours does, and explicitly set the header if not.
Distinguish 405 Data Not Found from 404 Symbol Not Found
Both can appear when something goes wrong with a request, but they mean different things:
- 404, the symbol itself is not in Kibot's catalogue (or is being fetched with the wrong &type=).
- 405, the symbol exists but Kibot has no data for the requested date range.
A retry strategy that lumps them together will retry symbol typos forever; treating them separately surfaces the actionable error to the caller.
Key Takeaways
200is the only success code; every other status carries information that callers should act on.403 Login Failedis overloaded for both bad credentials and rate-limit trips, disambiguate by tracking request rate, not by retrying.404 Not Foundfrom?action=adjustmentsis the documented success signal for "no changes since your cursor" and should be handled as a control-flow branch, not an error.404 Symbol Not Foundand405 Data Not Foundboth signal "we couldn't fulfil this" but mean different things (no such symbol vs. no data in this window) and need different retry logic.Accept-Encoding: gzip,deflateis always worth setting, tick and intraday responses compress 5–10×.- The server responds with
Content-Encoding: gzipwhen it compresses; auto-decompression is the default in most HTTP libraries but not all configurations.
Related
- API authentication, Login flow and the gotcha around
403reuse for rate limits. - Rate limits and throttling, How to disambiguate auth failure from rate-limit, and the recommended backoff pattern.
- Adjustments request, Where
404becomes a normal "nothing changed" signal. - History request, Where compression matters most because tick responses are large.
- Data updates, Per-server ceilings that produce
403when exceeded. - API client examples, Reference implementations showing
Accept-Encodingand decompression in five languages.