Trakt System SDK
Client libraries for the Trakt System Integrations API: fleet predictions and maintenance forecasts, in a few lines of code.
Trakt System predicts which components on your fleet need attention, when, and what to do about them. This SDK gives you that data directly, with authentication, retries, and rate limits handled for you.
Full API reference, with details on every endpoint: https://www.trakt.tech/api-documentation
Install
Python
pip install kquika-trakt # core
pip install "kquika-trakt[pandas]" # with DataFrame support
You install kquika-trakt, then write import trakt in your code.
The Python package also gives you a trakt command to run in your terminal. See
Command line.
Node / TypeScript
npm install @kquika-inc/trakt
Requires Node 18 or newer. TypeScript types are included.
Quickstart
Python
from trakt import Trakt
trakt = Trakt(token="YOUR_API_KEY") # or set TRAKT_TOKEN
# What can this token do?
cfg = trakt.config()
print(cfg.access_level, cfg.max_predictions, cfg.can_export)
# Per-component predictions, most urgent first
for c in trakt.components():
print(c.name, c.aircraft_tail_number, c.health,
c.failure_probability, c.recommended_action)
# The next 90 days of maintenance, soonest first
for item in trakt.forecast(days=90):
if item.is_overdue:
print("OVERDUE:", item.tail_number, item.component_name)
# Straight to a DataFrame for planning
df = trakt.components_dataframe()
# Fleet-level rollup that matches the dashboards: health, composite average
# confidence, prediction coverage, and 30-day survival
summary = trakt.fleet_summary()
print(summary.fleet_health, summary.avg_confidence, summary.survival_30d)
# Everything that changed since you last looked. Not charged against your
# interactive call allowance, so you can poll it every thirty seconds.
for change in trakt.iter_delta(since="2026-06-01T00:00:00Z"):
print(change.component_name, change.health_band, change.days_until_due)
print("resume from", trakt.last_cursor)
# Why a prediction says what it says
why = trakt.explanation(1421)
print(why.risk_level, why.method, why.most_likely_failure_mode)
for driver in why.top_contributors[:3]:
print(" ", driver.feature, driver.contribution, driver.direction)
Node / TypeScript
import { Trakt } from "@kquika-inc/trakt";
const trakt = new Trakt({ token: process.env.TRAKT_TOKEN! });
const cfg = await trakt.config();
console.log(cfg.access_level, cfg.max_predictions);
// Per-component predictions, most urgent first
const components = await trakt.components();
for (const c of components) {
console.log(c.name, c.aircraft_tail_number, c.health, c.recommended_action);
}
// The next 90 days of maintenance, soonest first
const forecast = await trakt.forecast({ days: 90 });
for (const item of forecast) {
if (item.is_overdue) console.log("OVERDUE:", item.tail_number, item.component_name);
}
// Fleet-level rollup that matches the dashboards
const summary = await trakt.fleetSummary();
console.log(summary.fleet_health, summary.avg_confidence, summary.survival_30d);
// Everything that changed since you last looked. Not charged against your
// interactive call allowance, so you can poll it every thirty seconds.
for await (const change of trakt.iterDelta({ since: "2026-06-01T00:00:00Z" })) {
console.log(change.component_name, change.health_band, change.days_until_due);
}
console.log("resume from", trakt.lastCursor);
// Why a prediction says what it says
const why = await trakt.explanation(1421);
console.log(why.prediction?.risk_level, why.explanation?.method);
Command line
The Python package includes a trakt command, so you can check your token or
pull predictions straight from the terminal with no code. It works the same way
as the Python client, including automatic retries.
export TRAKT_TOKEN=YOUR_API_KEY
trakt config # access level and limits for this token
trakt quota # remaining allowance on each meter
trakt summary # fleet health rollup
trakt components -n 20 # the 20 most urgent components
trakt components --aircraft-id 7 --priority high
trakt forecast --days 90 # next 90 days, soonest first
trakt forecast --days 90 --overdue # past due items only
trakt explain 1421 # drivers behind one prediction
trakt scenarios # planning scenarios, or `trakt scenarios 5` for one
components and forecast print a table. Every other command prints JSON. To
get JSON from any command, add --json right after trakt:
trakt --json components --type engine | jq '.[] | select(.health < 40)'
If your terminal says trakt: command not found, use python -m trakt in its
place. It accepts the same commands.
Streaming and exports
delta prints each component that changed, one per line. It also prints a
cursor, which is a bookmark for where this run stopped. Save the changes and the
cursor to separate files, then pass the cursor back next time to pick up where
you left off:
trakt delta --since 2026-06-01T00:00:00Z > changes.ndjson 2> cursor.txt
trakt delta --cursor "$(sed 's/^cursor: //' cursor.txt)" >> changes.ndjson
export downloads your whole fleet in one go. It needs a read_write or full
token.
trakt export --format csv -o fleet.csv
trakt export --format ndjson --offset 10000 -o fleet_page2.ndjson
If your fleet has more rows than one export returns, the command tells you
which --offset to use for the next batch.
Commands
| Command | Calls |
|---|---|
config |
GET /api/integrations/config |
health |
GET /api/health-check |
token |
GET /api/token/info |
status |
GET /api/integrations/status |
quota |
GET /api/integrations/quota |
summary |
GET /api/integrations/fleet/summary |
aircraft |
GET /api/integrations/aircraft/extended |
components |
GET /api/integrations/components/extended |
forecast |
GET /api/integrations/planner/forecast |
explain |
GET /api/integrations/predictions/{id}/explanation |
delta |
GET /api/integrations/predictions/delta |
export |
GET /api/integrations/fleet/bulk-export |
scenarios |
GET /api/integrations/scenarios[/{scenario_id}] |
deprecations |
GET /api/integrations/deprecations |
version |
none, prints the client version |
Run trakt <command> --help to see the options for any command.
Options and exit codes
--token and --base-url take priority over the TRAKT_TOKEN and
TRAKT_BASE_URL environment variables. --timeout sets how many seconds to
wait for each response. -v shows each request and retry as it happens.
Each command finishes with a number, so a script can tell what happened:
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Something went wrong with the API or your connection |
| 2 | The command was typed incorrectly |
| 3 | Your token was not accepted |
| 4 | Your token's access level does not allow this |
| 5 | Too many requests, even after automatic retries |
| 6 | An endpoint shuts down within your --fail-within window |
| 130 | You stopped the command |
The trakt command comes with the Python package only. In Node, use the client
in your code.
Full endpoint coverage
Both clients cover every endpoint your token can use. This table shows which method calls which endpoint.
| Method (Python / Node) | Endpoint |
|---|---|
config / config |
GET /api/integrations/config |
health_check / healthCheck |
GET /api/health-check |
token_info / tokenInfo |
GET /api/token/info |
integration_status / integrationStatus |
GET /api/integrations/status |
components / components |
GET /api/integrations/components/extended |
available_predictions / availablePredictions |
GET /api/integrations/predictions/available |
forecast / forecast |
GET /api/integrations/planner/forecast |
planner_grid / plannerGrid |
GET /api/integrations/planner/grid |
failure_windows / failureWindows |
GET /api/integrations/predictions/failure-windows |
failure_instances / failureInstances |
GET /api/integrations/predictions/failure-instances |
probability_between / probabilityBetween |
GET /api/integrations/predictions/probability-between |
select_predictions / selectPredictions |
POST /api/integrations/predictions/select |
export_predictions / exportPredictions |
POST /api/integrations/predictions/export |
convert_prediction / convertPrediction |
POST /api/integrations/planner/convert-prediction |
submit_optimizer_feedback / submitOptimizerFeedback |
POST /api/integrations/optimizer/feedback |
aircraft / aircraft |
GET /api/integrations/aircraft/extended |
fleet_export / fleetExport |
GET /api/integrations/fleet/export |
fleet_summary / fleetSummary |
GET /api/integrations/fleet/summary |
scenarios, create_scenario / scenarios, createScenario |
GET, POST /api/integrations/scenarios |
scenario / scenario |
GET /api/integrations/scenarios/{scenario_id} |
asset_configurations, create_asset_configuration / assetConfigurations, createAssetConfiguration |
GET, POST /api/integrations/asset-configurations |
maintenance_programs / maintenancePrograms |
GET /api/integrations/maintenance-programs |
submit_sensor_data / submitSensorData |
POST /api/v1/sensor-data/batch |
submit_aircraft / submitAircraft |
POST /api/v1/aircraft/batch |
submit_components / submitComponents |
POST /api/v1/components/batch |
submit_maintenance / submitMaintenance |
POST /api/v1/maintenance/batch |
submit_work_orders / submitWorkOrders |
POST /api/v1/work-orders/batch |
delta, iter_delta / delta, iterDelta |
GET /api/integrations/predictions/delta |
bulk_export / bulkExport |
GET /api/integrations/fleet/bulk-export |
explanation / explanation |
GET /api/integrations/predictions/{id}/explanation |
explanations / explanations |
POST /api/integrations/predictions/explanations/bulk |
convert_predictions_bulk / convertPredictionsBulk |
POST /api/integrations/planner/convert-predictions/bulk |
quota / quota |
GET /api/integrations/quota |
deprecations / deprecations |
GET /api/integrations/deprecations |
Two of these are being retired. select_predictions and export_predictions
stop working on 2026-12-31. Switch to delta and bulk_export before then.
Both clients print a warning the first time you call a retiring endpoint, so you
see the deadline in your own logs well ahead of time.
Staying in sync
The change feed returns only what changed since you last checked. Checking often costs nothing from your regular call allowance.
cursor = load_cursor() # whatever you stored last run
page = trakt.delta(cursor=cursor, limit=500)
for change in page:
upsert(change)
if page.next_cursor:
save_cursor(page.next_cursor)
Or let the client follow the cursor to the end:
for change in trakt.iter_delta(cursor=cursor):
upsert(change)
save_cursor(trakt.last_cursor)
Each row holds the full current state of a component. If a run fails partway, start again from your saved cursor and your copy catches up on its own. You need no extra recovery code.
To get notified automatically, register a webhook URL. Trakt sends a message to it when a component's health band changes, when a new critical prediction appears, or when an item becomes overdue. Set this up in the app under Integrations, Event Notifications.
Understanding a prediction
Each prediction comes with an explanation. It shows which sensor readings pushed the risk up or down, and how likely each type of failure is.
why = trakt.explanation(component_id)
print(why.explanation_text)
print("attribution from:", why.method)
for driver in why.top_contributors:
print(driver.feature, driver.contribution, driver.direction)
print("most likely mode:", why.most_likely_failure_mode)
print(why.failure_mode_probabilities)
A positive contribution raises failure risk and a negative one lowers it.
Check method before you quote any of these numbers. It tells you whether the
explanation came from a trained model or from a simpler rule of thumb, and a
report should say which.
To explain many components at once, explanations() takes up to fifty component
IDs in one call.
Working at fleet scale
# Two hundred conversions in one request, with per-row results
result = trakt.convert_predictions_bulk(
items=[{"component_id": cid} for cid in approved],
defaults={"work_type": "inspection"},
dry_run=True, # validate first, write nothing
)
print(result["succeeded"], "of", result["requested"])
for row in result["results"]:
if not row["success"]:
print("row", row["index"], "failed:", row["error"])
# The whole fleet in one pass, as a file
export = trakt.bulk_export(format="csv")
open(export["filename"], "w").write(export["content"])
Each row is handled on its own, so one bad row leaves the others unaffected.
Check results to see how each row did, since the call as a whole can succeed
while some rows fail. Running the same call twice creates duplicate work
orders.
Sending data in
The five upload methods accept up to 1,000 records per call. When some rows fail, the call still completes and reports which ones failed, so always check the counts:
result = trakt.submit_sensor_data([
{"component_id": 1, "timestamp": "2026-02-13T09:00:00Z",
"temperature": 85.2, "external_id": "fdr-abc-001"},
])
print(result["stored"], result["duplicates"], result["rejected"])
for error in result["errors"]:
print(error["row"], error["reason"])
A row is rejected if it has invalid data or points to a component outside your
company. The error tells you the row's position in your list, and the rest of
the batch is still saved. Add an external_id to each row to make retries safe:
sending the same ID and timestamp again is counted as a duplicate and stored
only once.
For more than 1,000 records, split them into several calls yourself. That way, if something fails, you know exactly which call it was.
Handling errors
Each kind of failure has its own error type, so you can handle each one separately.
from trakt import (
AuthenticationError, PermissionError_, RateLimitError, EndpointRetiredError
)
try:
components = trakt.components()
except AuthenticationError:
print("The token was not accepted.")
except PermissionError_:
print("This token's access level does not cover that call.")
except RateLimitError:
print("An allowance is exhausted. The client already retried with backoff.")
except EndpointRetiredError as e:
print("That endpoint is gone. Use", e.successor)
import {
AuthenticationError, PermissionError, RateLimitError, EndpointRetiredError
} from "@kquika-inc/trakt";
try {
const components = await trakt.components();
} catch (e) {
if (e instanceof AuthenticationError) console.error("The token was not accepted.");
else if (e instanceof PermissionError) console.error("Access level does not cover that call.");
else if (e instanceof RateLimitError) console.error("An allowance is exhausted.");
else if (e instanceof EndpointRetiredError) console.error("Gone. Use", e.successor);
else throw e;
}
RateLimitError tells you which allowance ran out. Call quota() to see how
much you have left and when it resets.
Deprecation notices
When you call an endpoint that is being retired, the API tells you the shutdown date and which endpoint replaces it. Both clients pass this notice on to you, so the deadline shows up in your logs well before the endpoint stops working.
Python raises a TraktDeprecationWarning, once per endpoint per client:
import warnings
from trakt import TraktDeprecationWarning
warnings.simplefilter("error", TraktDeprecationWarning) # fail your CI on one
warnings.simplefilter("ignore", TraktDeprecationWarning) # or silence it
Node calls console.warn by default, and takes a handler:
const trakt = new Trakt({
token: process.env.TRAKT_TOKEN!,
onDeprecation: (notice) => {
logger.warn({ path: notice.path, sunset: notice.sunset,
successor: notice.successor }, notice.message);
},
});
GET /api/integrations/deprecations lists every endpoint scheduled to shut down
and when. Both clients offer it as deprecations(). You can also add the command
below to your build, so the build fails when any shutdown is within the number
of days you set:
trakt deprecations --fail-within 60
What the clients do for you
- Sign in once. Set your token once and every request uses it.
- Automatic retries. If you hit a rate limit or the server has a brief problem, the client waits and tries again, following the server's guidance on how long to wait. A rejected token or a permission error is not retried, since trying again would give the same result.
- Clear errors.
AuthenticationError,PermissionError,RateLimitError,NotFoundError,ServerError. - Simple objects. Prediction, survival, and maintenance details sit directly
on each component, so
healthandrecommended_actionare easy to reach. - Predictable ordering. Every list comes back in the same order every time, most urgent first wherever urgency applies. See Ordering below.
- A terminal command. The Python package includes
traktfor everyday tasks with no code.
Ordering
| Method | Order |
|---|---|
components, available_predictions / availablePredictions, select_predictions / selectPredictions |
Most urgent first: highest failure probability, then lowest health. |
forecast |
Most urgent first (critical, high, medium, normal), then soonest due within each level. Past due items have a negative days_until_due. |
failure_windows / failureWindows |
Soonest expected failure first: least remaining life, then lowest health. |
failure_instances / failureInstances |
Within each instance, earliest failure day first. |
scenarios, integration_status / integrationStatus |
Newest first. |
explanations |
The order of the component IDs you passed. |
delta, iter_delta / iterDelta |
Oldest change first. |
The change feed is the one list that runs oldest first, on purpose. It records
each change in the order it happened, so your copy stays correct when you apply
them in turn. Applied newest first, an older value would overwrite a newer one,
and picking up from your saved bookmark would skip changes. For the current
state of the fleet, most urgent first, use components.
If your token has a limit on how many components it returns (see
max_predictions in config()), components, available_predictions,
failure_windows, and forecast return the most urgent components within that
limit, not the first ones created.
Reading the fields
| Field | Meaning |
|---|---|
health |
0 to 100, where higher is healthier. |
health_trend |
stable, declining, or critical. |
predicted_rul_hours / predicted_rul_days |
Remaining useful life before attention is due. |
failure_probability |
0 to 1, the modeled chance of failure in the near term. |
recommended_action |
do_nothing, monitor, inspect, repair, or replace. |
priority |
How urgent the item is, for planning. |
task_reference |
The task ID from your own maintenance system, so you can match each row to it. |
days_until_due |
Negative means the item is already past due. |
Access levels
Your token is issued at one of three levels, which control both the endpoints it can reach and how many records a request returns:
read_only: predictions, forecasts, explanations, and the change feedread_write: adds exports, bulk operations, and work order conversionfull: everything
A call outside your token's level raises a permission error. Call config() to
see the level and limits for your token.
Allowances
Usage is tracked in three separate allowances. Keeping your data up to date never eats into the calls your app needs:
| Meter | What it covers | Priced |
|---|---|---|
interactive |
Everyday requests your app makes | Per call, against your plan's daily and monthly limit |
feed |
Checking the change feed | Enough to check every thirty seconds, on every access level including read_only |
bulk |
Whole-fleet exports and batch uploads | Once per operation, whatever the size |
A 50,000 row export costs the same as a 5 row export. Keeping a live copy of your fleet data costs nothing from your app's everyday allowance.
q = trakt.quota()
print(q.interactive.daily_remaining, "interactive calls left today")
print(q.feed.daily_remaining, "feed polls left today")
print(q.bulk.monthly_remaining, "bulk operations left this month")
Every response also includes your remaining allowance in the X-Trakt-Quota-*
headers. When an allowance runs out, the API returns error 429 with the number
of seconds until it resets. Both clients wait that long and retry for you.
Need a client in another language?
You can download a description of the whole API and use a code generator to build a client in your own language. The file always matches the live API:
curl -LO https://www.trakt.tech/api/openapi.yaml # YAML format
curl -LO https://www.trakt.tech/api/openapi.json # JSON format
Downloading these files needs no token, since they contain no customer data. Calling the API itself still needs your token.
For example, to generate a Go client:
openapi-generator-cli generate \
-i https://www.trakt.tech/api/openapi.yaml \
-g go -o ./trakt-go
Citation
If Trakt informs a paper, technical report, reliability study, or regulatory submission, cite the release you actually ran.
You can cite two things. Cite Trakt System when your results use its predictions, which covers most cases. Cite the client library as well when your work is about the client itself, or when a reviewer needs to repeat the exact calls you made.
Citing Trakt System
The API documentation always shows the up-to-date Trakt System citation in BibTeX, APA, IEEE, and CITATION.cff formats: https://www.trakt.tech/api-documentation#citation
Copy it from that page. This README leaves the platform version out on purpose, since it would go stale with each new release.
Citing this client
BibTeX
@misc{kquika2026traktpy,
title = {Trakt System Python SDK},
author = {{Kquika, Inc.}},
year = {2026},
version = {1.3.2},
publisher = {{Kquika, Inc.}},
howpublished = {\url{https://pypi.org/project/kquika-trakt/}},
url = {https://pypi.org/project/kquika-trakt/},
note = {Computer software, version 1.3.2}
}
@misc{kquika2026traktjs,
title = {Trakt System Node SDK},
author = {{Kquika, Inc.}},
year = {2026},
version = {1.2.2},
publisher = {{Kquika, Inc.}},
howpublished = {\url{https://www.npmjs.com/package/@kquika-inc/trakt}},
url = {https://www.npmjs.com/package/@kquika-inc/trakt},
note = {Computer software, version 1.2.2}
}
These use @misc because every BibTeX style accepts it. If you use biblatex,
you can change it to @software and delete the howpublished line.
APA 7th
Kquika, Inc. (2026). Trakt System Python SDK (Version 1.3.2) [Computer software]. https://pypi.org/project/kquika-trakt/
Kquika, Inc. (2026). Trakt System Node SDK (Version 1.2.2) [Computer software]. https://www.npmjs.com/package/@kquika-inc/trakt
In text: (Kquika, Inc., 2026).
IEEE
Kquika, Inc., "Trakt System Python SDK," version 1.3.2, 2026. [Online]. Available: https://pypi.org/project/kquika-trakt/
Kquika, Inc., "Trakt System Node SDK," version 1.2.2, 2026. [Online]. Available: https://www.npmjs.com/package/@kquika-inc/trakt
CITATION.cff
Save this as CITATION.cff in the top folder of your project, and citation
tools will find it. Keep the entry for the client you use.
cff-version: 1.2.0
message: "If you use Trakt in your work, please cite it as below."
title: "Trakt System Python SDK"
type: software
version: "1.3.2"
license: MIT
url: "https://pypi.org/project/kquika-trakt/"
repository-artifact: "https://pypi.org/project/kquika-trakt/"
authors:
- name: "Kquika, Inc."
For the Node client, change title to Trakt System Node SDK, version to
1.2.2, and both URLs to
https://www.npmjs.com/package/@kquika-inc/trakt.
Reporting the version
State the client version in your methods section. The client sends its version with every request, so your results can be matched to our server records:
trakt-python/1.3.2
trakt-node/1.2.2
Print it from your code, so the version you report always matches the one you ran:
import trakt
print(trakt.__version__)
trakt --version
import { VERSION } from "@kquika-inc/trakt";
console.log(VERSION);
Predictions also depend on which model produced them, and models are updated on
their own schedule. Every change feed row includes model_version, and every
explanation includes model_version and active_model. Record these next to the
client and API versions, so readers know exactly which model produced your
results:
versions = {c.model_version for c in trakt.iter_delta(since=study_start)}
why = trakt.explanation(component_id)
print(why.model_version, why.active_model)
const why = await trakt.explanation(componentId);
console.log(why.prediction?.model_version, why.active_model);
If your results include more than one model_version, they came from more than
one model. Report each one, or limit your analysis to a single model.
Support
API reference: https://www.trakt.tech/api-documentation
For questions, a new token, or a higher limit: support@kquika.com
License
MIT
Metadata
Release files for kquika-trakt 1.3.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| kquika_trakt-1.3.2.tar.gz | 34.2 kB | Without provenance | Details for kquika_trakt-1.3.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| kquika_trakt-1.3.2-py3-none-any.whl | Python 3 | none | any | Details for kquika_trakt-1.3.2-py3-none-any.whl |
Total release size: 68.1 kB
Release files / kquika_trakt-1.3.2.tar.gz
| Download URL | kquika_trakt-1.3.2.tar.gz |
|---|---|
| Size | 34.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
397e8418e3cb41a4c6c30f96bea2bcbeb8e6a1a87bb31456d24b40a00b0ed0c7
|
|
BLAKE2b-256 checksum How to use checksums |
c01f1b9c5fde1e0dc97a06d5e5bd2801fe71eb638af8269578ce8a8313ece7f4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.9
|
Release files / kquika_trakt-1.3.2-py3-none-any.whl
| Download URL | kquika_trakt-1.3.2-py3-none-any.whl |
|---|---|
| Size | 33.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3d18112a1b9b28179ef6911cc010e30b63196f0952af08d31788cab9af9b57de
|
|
BLAKE2b-256 checksum How to use checksums |
856d4f119b80811bae85769d7eb3cd1e8062e5126c66f07b72263b27e8c49a98
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.9
|
Security for kquika-trakt 1.3.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.