Kekoa Enterprise API Specification
Introduction
The Kekoa Enterprise API enables enterprise customers to seamlessly integrate Kekoa’s predictive models into their systems, delivering clear, actionable trade signals for informed decision-making. Please follow the guidelines of the API and in case of any questions, please get in touch with relevant personnel.
This document should be utilized by users/clients/customers while designing their solutions.
Environment
To begin using the APIs, please use the base URL provided to you along with your access credentials.
In this document, that URL will be referred to as <base_url>. All APIs respond with data in application/json format.
Authentication API
This section defines how enterprise clients authenticate before calling Kekoa Enterprise APIs.
Enterprise API access does not use the Organization Admin’s email, password, or OTP. Instead, the ‘client application’ authenticates using application-level credentials generated from the API Access screen.
1. Authentication Flow
- Organization Admin creates an API token from the Kekoa API Access screen.
- System generates:
- appId
- apiToken
- The API token is emailed to the currently logged-in Organization Admin’s registered email.
- Client application calls the Authentication API using appId and apiToken.
- Kekoa returns a short-lived accessToken.
- Client uses the accessToken to call Enterprise APIs.
- Once the token expires, the client requests a new access token using the same appId and apiToken.
2. Generate Access Token
Endpoint
Request
Content-Type: application/json
{
"appId": "app_9f3a72d1",
"apiToken": "kekoa_api_XXXXXXXXXXXXXXXX"
}
Request Fields
| Field | Required | Description |
|---|---|---|
| appId | Yes | Application identifier generated for the organization |
| apiToken | Yes | API token generated from the API Access screen and emailed to the Organization Admin |
3. Authentication Response
Success Response
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"tokenType": "Bearer",
"expiresIn": 3600,
"expiresAt": "2026-04-02T01:00:00Z"
}
Response Fields
| Field | Description |
|---|---|
| accessToken | Short-lived bearer token used to call Enterprise APIs |
| tokenType | Token type. Value will be Bearer |
| expiresIn | Token lifetime in seconds |
| expiresAt | Exact UTC expiry time |
4. Using the Access Token
The client includes the access token in the Authorization header for all Enterprise API requests.
Authorization: Bearer <accessToken>
5. Token Expiry and Refresh Behavior
For the initial version, there is no separate refresh token.
When the access token expires, the client must call the Authentication API again using the same valid appId and apiToken.
Refresh Flow
- Access token expires.
- API request returns 401 UNAUTHORIZED.
- Client calls /v1/auth/token again with:
- appId
- apiToken
- Kekoa issues a new short-lived access token.
- Client retries the API request with the new token.
Refresh Request
Content-Type: application/json
{
"appId": "app_9f3a72d1",
"apiToken": "kekoa_api_XXXXXXXXXXXXXXXX"
}
Refresh Response
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.new...",
"tokenType": "Bearer",
"expiresIn": 3600,
"expiresAt": "2026-04-02T02:00:00Z"
}
6. Expired Token Error Example
{
"error": {
"code": "ACCESS_TOKEN_EXPIRED",
"message": "The access token has expired. Please request a new access token using your appId and apiToken."
}
}
7. Invalid Credentials Error Example
{
"error": {
"code": "INVALID_CREDENTIALS",
"message": "The provided appId or apiToken is invalid."
}
}
8. Recommended Approach
For the initial implementation:
Use appId + apiToken to issue short-lived access tokens. Do not introduce refresh tokens yet. After timeout, the client simply requests a new access token using the same application credentials.
This keeps the authentication model simple and suitable for machine-to-machine enterprise API usage.
Signals API – Sample Request & Response
This section illustrates how enterprise clients will interact with the Kekoa Signals API and what kind of data they can expect in response.
Sample Request
Authorization: Bearer <access_token>
Request Parameters
| Parameter | Description | Required |
|---|---|---|
| symbol | Trading symbol for which signals are requested | Yes |
| interval | Timeframe for signal generation (15m, 1h, 1d, 1w) | Yes |
| start | Start of the time range (ISO 8601 format) | Yes |
| end | End of the time range (ISO 8601 format) | Yes |
Data Availability & Limits
6.1 Supported Time Range (by Interval)
The maximum allowable time range depends on the selected interval.
| Interval | Maximum Lookback |
|---|---|
| 15m | Up to 30 days |
| 1h | Up to 45 days |
| 1d | Up to 3 years |
| 1w | Up to 5 years |
Important Notes
- The start and end parameters must fall within the allowed range for the selected interval
- Requests exceeding the allowed range will be rejected
- Clients should design queries accordingly based on interval granularity
Sample Response
{
"symbol": "JOBY",
"interval": "1h",
"signals": [
{
"name": "Bullish Inside Day",
"timestamp": "2026-03-05T13:00:00Z",
"price": 9.415,
"type": "BUY",
"strength": "NORMAL"
}
]
}
Response Structure Explanation
Top-Level Fields
| Field | Description |
|---|---|
| symbol | The symbol requested by the client |
| interval | The timeframe used for signal generation |
| signals | List of signals returned for the given time range |
Signal Object
Each item in the signals array represents a generated trading signal.
| Field | Description |
|---|---|
| name | Name of the signal pattern |
| timestamp | The timestamp field represents the closing time of the candle for the specified interval at which the signal is generated. Example: - For interval 1h, the timestamp corresponds to the end of the 1-hour candle |
| price | The price field represents the closing price of the candle corresponding to the specified interval at the time the signal is generated. For interval 1h, the price represents the closing price of that 1-hour candle at the signal timestamp. |
| type | Signal direction (BUY or SELL) |
| strength | Indicates the confidence or intensity of the signal. The strength field is returned as a predefined enum to ensure consistency across all integrations. |
Strength Field Enum (Allowed Values)
| Value | Description |
|---|---|
| WEAK | Low confidence signal, may require additional confirmation |
| NORMAL | Standard signal strength based on defined criteria |
| STRONG | High confidence signal with stronger supporting indicators |
| VERY STRONG | Highest confidence signal with very strong supporting indicators |
Example Interpretation
For the sample response above:
- A Bullish Inside Day signal was generated
- At 2026-03-05 13:00 UTC
- At a price of 9.415
- Indicating a BUY opportunity
- With normal strength
Empty Response Example
If no signals are found:
{
"symbol": "JOBY",
"interval": "1h",
"signals": []
}
Notes
- The API returns all signals generated within the requested time range
- There is no fixed limit on the number of signals returned
Disclaimer and Confidentiality Notice
The information contained in these documents is confidential, privileged, and only for the understanding of the intended recipient and may not be used, published, or redistributed without prior written consent from the owner of this document.