Skip to content

Latest commit

 

History

History
142 lines (100 loc) · 5.48 KB

File metadata and controls

142 lines (100 loc) · 5.48 KB

QTSurfer API Client · Java

CI JitPack JDK 17+ License

Auto-generated Java client for the QTSurfer API, built from the OpenAPI 3.1 spec with openapi-generator and the JDK's java.net.http.HttpClient.

net.qtsurfer:api-client · com.github.QTSurfer:api-client-java


Intentionally thin: one method per endpoint, 1:1 with the spec. For workflow orchestration (polling, retries, domain objects, unified errors), use net.qtsurfer:sdk.

  • Zero HTTP runtime depsjava.net.http.HttpClient (JDK built-in) + Jackson for JSON.
  • Spec-driven — generated sources fetched from QTSurfer/qtsurfer-api on every build.
  • JDK 17+ — modern language features, long-term support.
  • Distributed via JitPack today; Maven Central later.

Installation

Via JitPack

Add the JitPack repository and the dependency:

<repositories>
  <repository>
    <id>jitpack.io</id>
    <url>https://jitpack.io</url>
  </repository>
</repositories>

<dependency>
  <groupId>com.github.QTSurfer</groupId>
  <artifactId>api-client-java</artifactId>
  <version>v0.1.2</version>
</dependency>

For Gradle:

repositories { maven { url 'https://jitpack.io' } }
dependencies { implementation 'com.github.QTSurfer:api-client-java:v0.1.2' }

Via Maven Central (future)

Once published to Central, the coordinate will be net.qtsurfer:api-client:0.1.2.

Quick start

import net.qtsurfer.api.client.api.ExchangeApi;
import net.qtsurfer.api.client.invoker.ApiClient;
import net.qtsurfer.api.client.model.Exchange;

import java.util.List;

ApiClient client = new ApiClient();
client.updateBaseUri("https://api.qtsurfer.net/v1");
client.setRequestInterceptor(builder ->
    builder.header("Authorization", "Bearer " + System.getenv("JWT_API_TOKEN")));

ExchangeApi exchanges = new ExchangeApi(client);
List<Exchange> result = exchanges.getExchanges();

API surface

API class Methods
ExchangeApi getExchanges(), getInstruments(exchangeId)
ExchangeBinaryDownloads getTickersHour(...), getKlinesHour(...) — Lastra/Parquet streams (manual; see note below)
StrategyApi postStrategy(body, xCompileAsync), getStrategyStatus(strategyId)
BacktestingApi prepareBacktesting, getPreparationStatus, executeBacktesting, cancelExecution, getExecutionResult

All generated model types (Exchange, InstrumentDetail, JobState, BacktestJobResult, ResultMap, ResponseError, …) live under net.qtsurfer.api.client.model.

Binary downloads (/exchange/{ex}/tickers|klines/{base}/{quote})

These endpoints return raw Lastra bytes (default) or Parquet (format=parquet). The auto-generated ExchangeApi.getExchangeTickersHour / getExchangeKlinesHour methods are unusable for binary payloads — openapi-generator's native library decodes the body as UTF-8 and feeds it to Jackson, which corrupts the bytes. Use ExchangeBinaryDownloads instead:

import net.qtsurfer.api.client.binary.ExchangeBinaryDownloads;
import net.qtsurfer.api.client.binary.ExchangeBinaryDownloads.Format;

ExchangeBinaryDownloads downloads = new ExchangeBinaryDownloads(client);
try (var in = downloads.getTickersHour("binance", "BTC", "USDT", "2026-01-15T10")) {
    Files.copy(in, Path.of("BTC_USDT_2026-01-15_h10.lastra"));
}

try (var in = downloads.getKlinesHour("binance", "BTC", "USDT", "2026-01-15T10", Format.PARQUET)) {
    // feed into Apache Parquet, DuckDB, etc.
}

The class reuses the ApiClient's HttpClient and request interceptor, so any Authorization header set at the client level applies automatically.

Configuring the client

ApiClient exposes the underlying HttpClient.Builder and an ObjectMapper, plus hooks for request/response interceptors.

client.updateBaseUri("https://api.qtsurfer.net/v1");

client.setRequestInterceptor(builder ->
    builder.header("Authorization", "Bearer " + token)
           .header("X-Request-Id", UUID.randomUUID().toString()));

client.setResponseInterceptor(response ->
    log.debug("HTTP {} {}", response.statusCode(), response.uri()));

Regenerating the client

Generated sources are produced by the openapi-generator-maven-plugin during the generate-sources phase and compiled from target/generated-sources/openapi. To regenerate:

mvn -B clean generate-sources

The input spec URL is configured in pom.xml (openapi.spec.url property). Point it to a tag or commit for reproducible builds.

Development

Command Description
mvn verify Fetch spec, generate, compile, run tests, build jar + sources + javadoc
mvn clean Remove target/

License

Apache-2.0 — see LICENSE.