REST endpoints - basics
Authentication
Before you can make any request to a Genesis component, you must have made an initial log in to the application and retrieved the SESSION_AUTH_TOKEN
.
EVENT_LOGIN_AUTH
Log in requests are submitted via POST requests to
[host]:[genesis_router_port]/event-login-auth
.
Initial login requests require:
USER_NAME
andPASSWORD
keys in theDETAILS
objectSOURCE_REF
header.
Sample request:
POST /event-login-auth HTTP/1.1
Host: localhost:9064
Content-Type: application/json
SOURCE_REF: 123456-789041
{
"DETAILS": {
"USER_NAME": "admin",
"PASSWORD": "genesis"
}
}
Sample response:
{
"MESSAGE_TYPE": "EVENT_LOGIN_AUTH_ACK",
"SESSION_AUTH_TOKEN": "y9lNIRTax0pmTdUN0XC1PgVl32KuXGsf",
"REFRESH_AUTH_TOKEN": "FmqF9CGzo2MiujEZoiRUjGXh8ybDC62L",
"SESSION_ID": "3f0203a5-e89d-4245-9e8b-c21fb0bcacd9",
"USER_ID": "",
"DETAILS": {
"SYSTEM": {
"DATE": "Sun Jan 21 20:53:44 UTC 2018"
},
"HEARTBEAT_INTERVAL_SECS": 30,
"FAILED_LOGIN_ATTEMPTS": 0,
"REJECTED_LOGIN_ATTEMPTS": 0,
"LAST_LOGIN_DATETIME": 1516567765917,
"PRODUCT": [
{
"NAME": "dta",
"VERSION": "2.2.2"
},
{
"NAME": "auth",
"VERSION": "1.1.1"
}
]
},
"SOURCE_REF": "123456-789041"
}
Once the SESSION_AUTH_TOKEN
has been returned, you must add it to every future request, except EVENT_LOGIN_REFRESH
and EVENT_LOGOUT
: more on that later.
Data Server
Every query
specified inside your application's dataserver.kts file is exposed as an HTTP endpoint; these are the most complex of the REST Endpoints provided by the Genesis platform. HTTP requests can only have a single response, but the Data Server enables you to publish a continuous stream of data to a subscribing client.
For all Data Server requests, a SOURCE_REF
header is mandatory, which is used to match requests to the correct client subscription. This allows for multiple subscriptions to the same query for the same session (think multiple grids in the UI using the same query with different filters).
Endpoint
The endpoints have names that follow the lower-case hyphen-separated web standards convention (for example, ALL_TRADES becomes all-trades). There is no need to rename your Data Server resource; the endpoint is automatically formatted to the correct naming convention when it is exposed.
The endpoint url is typically in the following format:
[host]:[genesis_router_port]/[data_server_query_name]
.
POST
A POST request creates a new subscription to a Data Server query; it is equivalent to a DATA_LOGON message sent over Websockets.
The request body is optional; if provided, it can contain Data Server parameters, such as MAX_ROWS
and `FIELDS. Alternatively, these parameters can be provided as HTTP query parameters. See more information in the Data Server data logon messages section.
The response contains the initial set of data for the subscription. The ROW_REF
is a unique handle to each row returned and is present on all QUERY_UPDATE requests where the given row has changed (e.g. modify/delete).
From this moment onward, real-time data updates for the subscription are cached in the back end until the next GET method call.
To avoid memory leaks, the server will timeout subscriptions that have not been active for a specified period (no GET or PUT requests received). At this point, a new subscription can be made via a new DATA_LOGON request. See the Genesis Router configuration for more information about the dataserverPollingTimeout
configuration option.
Here is an example request:
POST http://localhost:9064/all-trades
Content-Type: application/json
SOURCE_REF: 123456-789042
SESSION_AUTH_TOKEN: G21sF8S9z5J9FTw8iFLk6ZveK9LbMe6h
USER_NAME: admin
{
"DETAILS": {
"MAX_ROWS": 2,
"MAX_VIEW": 10,
"FIELDS": "PRICE QUANTITY TRADE_ID SYMBOL SIDE"
}
}
And here is an example response:
HTTP/1.1 200 OK
content-type: application/json
content-length: 350
connection: keep-alive
{
"ROWS_COUNT": 100,
"MESSAGE_TYPE": "QUERY_UPDATE",
"ROW": [
{
"PRICE": 100.25,
"QUANTITY": 50,
"TRADE_ID": "TRADE_001",
"SYMBOL": "AAPL",
"SIDE": "Buy",
"DETAILS": {
"OPERATION": "INSERT",
"ROW_REF": "7169357821048261343"
}
},
{
"PRICE": 99.75,
"QUANTITY": 75,
"TRADE_ID": "TRADE_002",
"SYMBOL": "GOOG",
"SIDE": "Sell",
"DETAILS": {
"OPERATION": "INSERT",
"ROW_REF": "7169357821044067038"
}
}
],
"MORE_ROWS": true,
"SOURCE_REF": "123456-789042",
"SEQUENCE_ID": 1
}
If pagination is required, the VIEW_NUMBER parameter can be provided:
POST http://localhost:9064/all-trades
Content-Type: application/json
SOURCE_REF: 123456-789042
SESSION_AUTH_TOKEN: G21sF8S9z5J9FTw8iFLk6ZveK9LbMe6h
USER_NAME: admin
{
"DETAILS": {
"MAX_ROWS": 2,
"VIEW_NUMBER": 1
"FIELDS": "PRICE QUANTITY TRADE_ID SYMBOL SIDE"
}
}
GET
Use the GET method to retrieve real-time updates from the subscription. No payload is necessary in the GET request body, only the URL and the relevant HTTP headers.
As explained in the previous section, the Data Server subscription will be destroyed if it is not queried within the configured polling timeout period.
The SOURCE_REF
should match that used in the original DATA_LOGON (subscription).
The response contains the update of data (new/modified/deleted rows since the last update). The ROW_REF
value is used to reference the given row previously returned. An empty QUERY_UPDATE response means there was no change to the underlying data since the last request.
Sample request:
GET http://localhost:9064/all-trades
Content-Type: application/json
SOURCE_REF: 123456-789042
SESSION_AUTH_TOKEN: G21sF8S9z5J9FTw8iFLk6ZveK9LbMe6h
USER_NAME: admin
Sample response:
HTTP/1.1 200 OK
content-type: application/json
content-length: 362
connection: keep-alive
{
"MESSAGE_TYPE": "QUERY_UPDATE",
"ROW": [
{
"DETAILS": {
"OPERATION": "DELETE",
"ROW_REF": "12345678901234567890"
}
},
{
"PRICE": 55.75,
"QUANTITY": 100,
"TRADE_ID": "TRADE_003",
"SYMBOL": "AAPL",
"SIDE": "Buy",
"DETAILS": {
"OPERATION": "INSERT",
"ROW_REF": "09876543210987654321"
}
},
{
"QUANTITY": 150,
"DETAILS": {
"OPERATION": "MODIFY",
"ROW_REF": "13579246801357924680"
}
}
],
"SOURCE_REF": "123456-789042"
}
PUT
PUT messages are slightly different from other Data Server messages; specifically, the SOURCE_REF
should be unique. A SUBSCRIPTION_REF
is also needed and must match the SOURCE_REF
value used in the original DATA_LOGON (subscription). The reason for the change in this message is that the response is a simple ACK/NACK, and the client should use this to know if it was successful or not.
MORE_COLUMNS
It is possible to change the columns supplied on updates to the given subscription to a Data Server query.
If an ACK is received, a further GET for the original SOURCE_REF
(this request's SUBSCRIPTION_REF
) will provide the added columns for each row the client has received, but nothing regarding the deleted columns. So the ACK is a means of telling the client it is OK to remove the deleted columns from the UI.
The body of this request should contain a DETAILS
object with ADD_COLUMNS
(further replies should include these columns) and/or DROP_COLUMNS
(further QUERY_UPDATE messages should not include these columns)
Below is an example of a full message flow, from subscription creation to successful column addition:
Subscription creation:
POST http://localhost:9064/all-trades
Content-Type: application/json
SOURCE_REF: 123456-789042
SESSION_AUTH_TOKEN: G21sF8S9z5J9FTw8iFLk6ZveK9LbMe6h
USER_NAME: admin
{
"DETAILS": {
"MAX_ROWS": "2",
"MAX_VIEW": "10",
"FIELDS": "PRICE TRADE_ID SYMBOL SIDE"
}
}
Subscription response:
HTTP/1.1 200 OK
content-type: application/json
content-length: 297
connection: keep-alive
{
"ROWS_COUNT": 100,
"MESSAGE_TYPE": "QUERY_UPDATE",
"ROW": [
{
"PRICE": 55.75,
"TRADE_ID": "TRADE_001",
"SYMBOL": "AAPL",
"SIDE": "Buy",
"DETAILS": {
"OPERATION": "INSERT",
"ROW_REF": "7169357821048261343"
}
},
{
"PRICE": 60.25,
"TRADE_ID": "TRADE_002",
"SYMBOL": "GOOG",
"SIDE": "Sell",
"DETAILS": {
"OPERATION": "INSERT",
"ROW_REF": "7169357821044067038"
}
}
],
"MORE_ROWS": true,
"SOURCE_REF": "123456-789042",
"SEQUENCE_ID": 1
}
MORE_COLUMNS request:
PUT http://localhost:9064/all-trades
Content-Type: application/json
SOURCE_REF: 123456-789045
SESSION_AUTH_TOKEN: G21sF8S9z5J9FTw8iFLk6ZveK9LbMe6h
USER_NAME: admin
SUBSCRIPTION_REF: 123456-789042
{
"DETAILS": {
"ADD_COLUMNS": "QUANTITY"
}
}
MORE_COLUMNS response:
HTTP/1.1 200 OK
content-type: application/json
content-length: 64
connection: keep-alive
{
"MESSAGE_TYPE": "MORE_COLUMNS_ACK",
"SOURCE_REF": "123456-789045"
}
GET Request to retrieve updated data with QUANTITY column:
GET http://localhost:9064/all-trades
Content-Type: application/json
SOURCE_REF: 123456-789042
SESSION_AUTH_TOKEN: G21sF8S9z5J9FTw8iFLk6ZveK9LbMe6h
USER_NAME: admin
Response with updated data, including QUANTITY column:
HTTP/1.1 200 OK
content-type: application/json
content-length: 436
connection: keep-alive
{
"MESSAGE_TYPE": "QUERY_UPDATE",
"ROW": [
{
"QUANTITY": 100,
"DETAILS": {
"OPERATION": "MODIFY",
"ROW_REF": "7169357821048261343"
}
},
{
"QUANTITY": 150,
"DETAILS": {
"OPERATION": "MODIFY",
"ROW_REF": "7169357821044067038"
}
}
],
"SOURCE_REF": "123456-789042",
}
MORE_ROWS
Where the client has specified a MAX_ROWS
and has then received that number of rows, PUT requests can be used to request more rows.
You can also use MORE_ROWS in conjunction with MAX_VIEW, MOVING_VIEW and VIEW_NUMBER to implement infinite-scrolling and pagination solutions. More details can be found in the Data Server data logon messages section.
The reply will be a simple ACK/NACK. Assuming an ACK, the next QUERY_UPDATE request will include the additional rows.
Here is an example request:
PUT http://localhost:9064/all-trades
Content-Type: application/json
SOURCE_REF: 123456-789045
SESSION_AUTH_TOKEN: G21sF8S9z5J9FTw8iFLk6ZveK9LbMe6h
USER_NAME: admin
SUBSCRIPTION_REF: 123456-789042
And here is an example response:
HTTP/1.1 200 OK
content-type: application/json
content-length: 61
connection: keep-alive
{
"MESSAGE_TYPE": "MORE_ROWS_ACK",
"SOURCE_REF": "123456-789045"
}
Response to the next GET request, assuming the subscription had MAX_ROWS=2 and MAX_VIEW size has not been breached:
HTTP/1.1 200 OK
content-type: application/json
content-length: 372
connection: keep-alive
{
"MESSAGE_TYPE": "QUERY_UPDATE",
"ROW": [
{
"PRICE": 52.50,
"TRADE_ID": "TRADE_003",
"SYMBOL": "MSFT",
"SIDE": "Buy",
"QUANTITY": 200,
"DETAILS": {
"OPERATION": "INSERT",
"ROW_REF": "7169357821048261344"
}
},
{
"PRICE": 65.75,
"TRADE_ID": "TRADE_004",
"SYMBOL": "AMZN",
"SIDE": "Sell",
"QUANTITY": 75,
"DETAILS": {
"OPERATION": "INSERT",
"ROW_REF": "7169357821044067039"
}
}
],
"SOURCE_REF": "123456-789042",
}
If pagination is used in conjunction with MORE_ROWS messages, you must provide the VIEW_NUMBER payload as part of the body (or as a query parameter). When using pagination, the next GET request after a successful MORE_ROWS_ACK response will provide DELETE operations for all the rows that have been removed from the previous page and new INSERT operations for the new rows in the page.
So, in the case of a subscription using MAX_ROWS=2, 2 rows will be DELETED and 2 ROWS will be added.
Here is an example message flow for this:
Request page 3
PUT http://localhost:9064/all-trades
Content-Type: application/json
SOURCE_REF: 123456-789045
SESSION_AUTH_TOKEN: G21sF8S9z5J9FTw8iFLk6ZveK9LbMe6h
USER_NAME: admin
SUBSCRIPTION_REF: 123456-789042
{
"DETAILS": {
"VIEW_NUMBER": 3
}
}
Response to page request.
HTTP/1.1 200 OK
content-type: application/json
content-length: 61
connection: keep-alive
{
"MESSAGE_TYPE": "MORE_ROWS_ACK",
"SOURCE_REF": "123456-789045"
}
Get page 3 in the next GET call:
GET http://localhost:9064/all-trades
Content-Type: application/json
SOURCE_REF: 123456-789042
SESSION_AUTH_TOKEN: G21sF8S9z5J9FTw8iFLk6ZveK9LbMe6h
USER_NAME: admin
HTTP/1.1 200 OK
content-type: application/json
content-length: 372
connection: keep-alive
{
"MESSAGE_TYPE": "QUERY_UPDATE",
"ROW": [
{
"DETAILS": {
"OPERATION": "DELETE",
"ROW_REF": "7169357821048261344"
}
},
{
"DETAILS": {
"OPERATION": "DELETE",
"ROW_REF": "7169357821044067039"
}
},
{
"PRICE": 750.20,
"QUANTITY": 150,
"TRADE_ID": "TRADE_005",
"SYMBOL": "TSLA",
"SIDE": "Buy",
"DETAILS": {
"OPERATION": "INSERT",
"ROW_REF": "7169357821048261354"
}
},
{
"PRICE": 120.50,
"QUANTITY": 100,
"TRADE_ID": "TRADE_006",
"SYMBOL": "ORCL",
"SIDE": "Sell",
"DETAILS": {
"OPERATION": "INSERT",
"ROW_REF": "7169357821044067239"
}
}
],
"SOURCE_REF": "123456-789042",
}
DELETE
A DELETE request is made to signal the end of the subscription for the given SOURCE_REF
.
The SOURCE_REF
must match the one used in the original DATA_LOGON (subscription).
No body is required.
here is an example request:
DELETE http://localhost:9064/all-trades
Content-Type: application/json
SOURCE_REF: 123456-789042
SESSION_AUTH_TOKEN: G21sF8S9z5J9FTw8iFLk6ZveK9LbMe6h
USER_NAME: admin
And here is an example response:
HTTP/1.1 200 OK
content-type: application/json
content-length: 58
connection: keep-alive
{
"MESSAGE_TYPE": "LOGOFF_ACK",
"SOURCE_REF": "123456-789042"
}
Request Server
Request Servers are accessed via GET requests to:
[host]:[genesis_router_port]/[request_reply_name]
.
Any request parameters must be prefixed with request.
:
request.[request_parameter]=[value]
.
For example:
localhost:9064/req-counterparty-details?request.[request_parameter]=[value]&request.[request_parameter]=[value]
.
Parameter values can be wild-carded (*
, A*
, _A
, _A*
, etc.) or left blank (and assumed to be *
).
Request Server requests require:
SOURCE_REF
header (a unique value must be supplied on every request with a unique value)SESSION_AUTH_TOKEN
header- the request parameters
request.[request_parameter]=[value]
- the request details, for example:
DETAILS.MAX_ROWS=100
For example:
http://localhost:9064/req-counterparty-details?request.counterPartyId=*&DETAILS.MAX_ROWS=100
Here is an example request:
GET /req-counterparty-details?request.CPTY_TYPE=MARKET&request.CPTY_REGION=US HTTP/1.1
Host: localhost:9064
Content-Type: application/json
SESSION_AUTH_TOKEN: 83eLYBnlqjIWt1tqtJhKwTXJj2IL2WA0
SOURCE_REF: 123456-789021
And here is an example response:
{
"MESSAGE_TYPE": "REP_COUNTERPARTY_DETAILS",
"SOURCE_REF": "123456-789021",
"REPLY": [
{
"CPTY_NAME": "ROAD_RUNNER_FUNDS"
},
{
"CPTY_NAME": "COYOTE_BROKERING"
}
]
}
Event Handler
Events are submitted via POST requests to:
[host]:[genesis_router_port]/event-[<event-name>]
.
All resource paths should be prefixed with event-
.
For example, if order-insert
is our custom event route and event-
is the prefix:
localhost:9064/event-order-insert
Event Handler requests require:
SOURCE_REF
header (a unique value must be supplied on every request with a unique value)SESSION_AUTH_TOKEN
header- A request body as per your event handler inside the
DETAILS
object.
Here is an example request:
POST /event-order-insert HTTP/1.1
Host: localhost:9064
Content-Type: application/json
SESSION_AUTH_TOKEN: 83eLYBnlqjIWt1tqtJhKwTXJj2IL2WA0
SOURCE_REF: 123456-789011
{
"DETAILS": {
"INSTRUMENT_CODE":"VOD",
"QUANTITY":"100",
"PRICE":"225"
}
}
And here is an example response:
{
"MESSAGE_TYPE": "EVENT_ACK",
"SOURCE_REF": "123456-789011"
}