The library is a Java client for the Kraken REST API. It is organized around four core concepts:
KrakenAPI— The main entry point. A facade that exposes typed methods for implemented endpoints and generic methods for any endpoint.Endpoint<T>— Represents a single API call. Knows its HTTP method, URL path, parameters, and response type. Splits intoPublicEndpoint<T>(GET),PrivateEndpoint<T>(POST with HMAC signing) andFundingBetaEndpoint<T>(any HTTP method on/funding, with the nonce in a header).KrakenRestRequester— Interface that performs the actual HTTP request and response parsing.DefaultKrakenRestRequesteris the built-in implementation usingHttpsURLConnection.- Params / Response types — Each endpoint has dedicated parameter objects (
QueryParamsfor public,PostParamsfor private) and response records deserialized via Jackson.
sequenceDiagram
participant User
participant KrakenAPI
participant PublicEndpoint
participant QueryParams
participant RestRequester as DefaultKrakenRestRequester
participant Kraken as Kraken API
User->>KrakenAPI: assetInfo(["BTC", "ETH"])
KrakenAPI->>PublicEndpoint: new AssetInfoEndpoint(assets)
activate PublicEndpoint
PublicEndpoint->>QueryParams: new AssetInfoParams(assets, "currency")
deactivate PublicEndpoint
KrakenAPI->>RestRequester: execute(endpoint)
RestRequester->>PublicEndpoint: buildURL()
PublicEndpoint->>QueryParams: toMap()
QueryParams-->>PublicEndpoint: {asset: "BTC,ETH", aclass: "currency"}
PublicEndpoint-->>RestRequester: https://api.kraken.com/0/public/Assets?asset=BTC,ETH&aclass=currency
RestRequester->>Kraken: GET
Kraken-->>RestRequester: {"error": [], "result": {…}}
RestRequester->>RestRequester: deserialize into KrakenResponse<Map<String, AssetInfo>>
RestRequester->>RestRequester: unwrap result or throw KrakenException
RestRequester-->>KrakenAPI: Map<String, AssetInfo>
KrakenAPI-->>User: Map<String, AssetInfo>
sequenceDiagram
participant User
participant KrakenAPI
participant PrivateEndpoint
participant PostParams
participant NonceGen as KrakenNonceGenerator
participant Credentials as KrakenCredentials
participant RestRequester as DefaultKrakenRestRequester
participant Kraken as Kraken API
User->>KrakenAPI: ledgerInfo(params)
KrakenAPI->>PrivateEndpoint: new LedgerInfoEndpoint(params)
KrakenAPI->>RestRequester: execute(endpoint, credentials, nonceGenerator)
RestRequester->>NonceGen: generate()
NonceGen-->>RestRequester: "1712750400000"
RestRequester->>PrivateEndpoint: encodedParamsWith(nonce)
PrivateEndpoint->>PostParams: setNonce(nonce)
PrivateEndpoint->>PostParams: encoded()
PostParams-->>RestRequester: "nonce=1712750400000&asset=BTC,ETH&…"
RestRequester->>PrivateEndpoint: buildURL()
PrivateEndpoint-->>RestRequester: https://api.kraken.com/0/private/Ledgers
RestRequester->>Credentials: sign(url, nonce, encodedParams)
Note over Credentials: SHA-256(nonce + params)<br/>HMAC-SHA512(base64(secret), path + sha256)
Credentials-->>RestRequester: Base64 signature
RestRequester->>Kraken: POST with API-Key + API-Sign headers
Kraken-->>RestRequester: {"error": [], "result": {…}}
RestRequester->>RestRequester: deserialize into KrakenResponse<LedgerInfo>
RestRequester->>RestRequester: unwrap result or throw KrakenException
RestRequester-->>KrakenAPI: LedgerInfo
KrakenAPI-->>User: LedgerInfo
Funding (Beta) endpoints live under /funding/v1 and /funding/v2 and follow a different protocol: path parameters, query parameters in bracket notation for nested objects, GET, POST, PUT and DELETE requests, an optional JSON body, the nonce in the API-Nonce header, and responses that are not wrapped in the {error, result} envelope.
sequenceDiagram
participant User
participant KrakenAPI
participant FundingBetaEndpoint
participant FundingBetaParams
participant NonceGen as KrakenNonceGenerator
participant Credentials as KrakenCredentials
participant RestRequester as DefaultKrakenRestRequester
participant Kraken as Kraken API
User->>KrakenAPI: fundingFees(params)
KrakenAPI->>FundingBetaEndpoint: new FundingFeesEndpoint(params)
KrakenAPI->>RestRequester: execute(endpoint, credentials, nonceGenerator)
RestRequester->>NonceGen: generate()
NonceGen-->>RestRequester: "1712750400000"
RestRequester->>FundingBetaEndpoint: encodedBody()
FundingBetaEndpoint->>FundingBetaParams: encodedBody()
FundingBetaParams-->>RestRequester: "" (GET) or a JSON object
RestRequester->>FundingBetaEndpoint: buildURL()
FundingBetaEndpoint->>FundingBetaParams: toMap()
FundingBetaEndpoint-->>RestRequester: https://api.kraken.com/funding/v1/fees/{method_id}?amount=5
RestRequester->>Credentials: sign(path + "?" + query, nonce, body)
Note over Credentials: SHA-256(nonce + body)<br/>HMAC-SHA512(base64(secret), signed path + sha256)
Credentials-->>RestRequester: Base64 signature
RestRequester->>Kraken: GET with API-Key + API-Sign + API-Nonce headers
Kraken-->>RestRequester: {"fee": {…}, "withdrawal_fee_token": "…"}
RestRequester->>RestRequester: deserialize into FundingFees, or throw KrakenException on an HTTP error status
RestRequester-->>KrakenAPI: FundingFees
KrakenAPI-->>User: FundingFees
classDiagram
class KrakenAPI {
-KrakenCredentials credentials
-KrakenNonceGenerator nonceGenerator
-KrakenRestRequester restRequester
+serverTime() ServerTime
+assetInfo(assets) Map~String, AssetInfo~
+ticker(pairs) Map~String, Ticker~
+ledgerInfo(params) LedgerInfo
+query(PublicEndpoint~T~) T
+query(PrivateEndpoint~T~) T
+query(FundingBetaEndpoint~T~) T
+query(endpoint) JsonNode
+queryPublic(path) JsonNode
+queryPrivate(path) JsonNode
}
class Endpoint~T~ {
<<abstract>>
#String path
-String httpMethod
-TypeReference~T~ responseType
+buildURL() URL
+wrappedResponseType() JavaType
}
class PublicEndpoint~T~ {
-QueryParams queryParams
+buildURL() URL
}
class PrivateEndpoint~T~ {
-PostParams postParams
+encodedParamsWith(nonce) String
+buildURL() URL
}
class FundingBetaEndpoint~T~ {
-FundingBetaParams params
+encodedBody() String
+buildURL() URL
}
class KrakenRestRequester {
<<interface>>
+execute(PublicEndpoint~T~) T
+execute(PrivateEndpoint~T~, credentials, nonceGenerator) T
+execute(FundingBetaEndpoint~T~, credentials, nonceGenerator) T
}
class DefaultKrakenRestRequester {
-ObjectMapper OBJECT_MAPPER
}
class KrakenResponse~T~ {
<<record>>
+List~String~ error
+Optional~T~ result
}
class KrakenException {
+List~String~ errors
}
class KrakenCredentials {
+sign(url, nonce, params) String
+sign(signedPath, nonce, body) String
}
class KrakenNonceGenerator {
<<interface>>
+generate() String
}
Endpoint <|-- PublicEndpoint
Endpoint <|-- PrivateEndpoint
Endpoint <|-- FundingBetaEndpoint
KrakenRestRequester <|.. DefaultKrakenRestRequester
KrakenAPI --> KrakenRestRequester
KrakenAPI --> KrakenCredentials
KrakenAPI --> KrakenNonceGenerator
DefaultKrakenRestRequester ..> KrakenResponse : deserializes
KrakenResponse ..> KrakenException : throws on error
KrakenAPI provides four levels of access, from most to least typed:
| Tier | Methods | Return type | When to use |
|---|---|---|---|
| Custom endpoint | query(myEndpoint) |
Whatever the endpoint declares | You wrote your own PublicEndpoint/PrivateEndpoint/FundingBetaEndpoint for an endpoint the library doesn't implement |
| Typed | assetInfo(), ledgerInfo(), etc. |
Domain records | Endpoint has a dedicated implementation |
| Enum-based | query(Public.TICKER, params) |
JsonNode |
Endpoint is in the Public/Private enum but not yet typed |
| Raw path | queryPublic("Trades", params) |
JsonNode |
Endpoint isn't in the enum yet (e.g., newly added by Kraken) |
To add a new typed endpoint:
- Create a response record in the appropriate
response/package - Create a params class implementing
QueryParams(public) or extendingPostParams(private); extendJsonPostParamsinstead when the body contains arrays or nested objects, and overridegetContentType()on the endpoint to returnapplication/json. Funding (Beta) params extendFundingBetaParams, returning query parameters fromtoMap()and a JSON body frombody() - Create an endpoint class extending
PublicEndpoint<T>,PrivateEndpoint<T>orFundingBetaEndpoint<T> - Add a convenience method to
KrakenAPI
Steps 1 to 3 work just as well from outside the library, for an endpoint you need before it is implemented here. Step 4 is then replaced by handing the endpoint to KrakenAPI.query(...), which runs it through the configured KrakenRestRequester and signs private requests with the credentials and nonce generator the instance was built with:
KrakenAPI api = new KrakenAPI(key, secret);
MyResponse response = api.query(new MyEndpoint(params));A PrivateEndpoint queried on an instance built without credentials fails with an IllegalStateException naming the endpoint path.