Skip to content

Overview

Connection Details

GRVT's services are hosted in AWS Tokyo (ap-northeast-1).

For close partners with high trading volumes, we offer AWS PrivateLink.


Authentication

GRVT supports API Authentication via session cookies, and API keys.

You may follow the below steps to authenticate your requests.

This section is conveniently inlined at every authenticated endpoint for your convenience.

Authentication

In order to authenticate, you must first provision a valid API key. API keys can be provisioned via the GRVT UI.

# These are the variables you will need to set manually
GRVT_API_KEY="<insert_key_here>"
GRVT_SUB_ACCOUNT_ID="<insert_sub_account_id_here>"

Then, choose the environment you want to authenticate against.

# dev
GRVT_AUTH_ENDPOINT="https://edge.dev.gravitymarkets.io/auth/api_key/login"
# stg
GRVT_AUTH_ENDPOINT="https://edge.stg.gravitymarkets.io/auth/api_key/login"
# testnet
GRVT_AUTH_ENDPOINT="https://edge.testnet.grvt.io/auth/api_key/login"
# prod
GRVT_AUTH_ENDPOINT="https://edge.grvt.io/auth/api_key/login"

Now, let's create a cookie that will be used to authenticate with our API Services.

echo $GRVT_API_KEY
echo $GRVT_SUB_ACCOUNT_ID
echo $GRVT_AUTH_ENDPOINT

GRVT_COOKIE=$(
    curl $GRVT_AUTH_ENDPOINT \
        -H 'Content-Type: application/json' \
        -H 'Cookie: rm=true;' \
        -d "{ \"api_key\": \"$GRVT_API_KEY\" }" \
        -s -i \
        | grep -i 'set-cookie:' \
        | grep -o 'gravity=[^;]*'
);

echo $GRVT_COOKIE

Order Creation

Python SDK

We have a Python SDK available for usage. (link)

pip install grvt-pysdk

Step-by-Step Guide

For specific information on how to sign and create an order, here's a step-by-step guide, using our Python SDK:

Chain IDs

Network Ethereum L1 Chain ID GRVT L2 Chain ID
Sepolia (Dev) 11155111 327
Sepolia (Stg) 11155111 327
Sepolia (Testnet) 11155111 326
Mainnet 1 325

Encoding (Full vs Lite)

For more versatile usage, all our APIs and Websockets are offered in full and lite variants.

These variants are identical except for the JSON field_name used:

  • `full` uses the full field name, e.g. `order_id`
  • `lite` uses the shortened field name, e.g. `oi`

This is allows for users to trade off between simplicity and performance.


WebSocket Subscription

Request

Websocket subscriptions are initiated by sending a JSON RPC Request to the server.

They have the following structure:

  • stream: The stream to subscribe to
  • feed: The list of feeds to subscribe to
  • method: The JSONRPC method. This is always `"subscribe"`
  • is_full: Whether to subscribe to the `full` or `lite` feed.
{
    "stream":"v1.book.s",
    "feed":["BTC_USDT_Perp@500-100-10"],
    "method":"subscribe",
    "is_full":true
}

Response

Upon subscribing, the server will respond with an initial JSON RPC Response.

In the successful case, the following response will be returned:

  • stream: The stream that was subscribed to
  • subs: The list of subscriptions that were successfully subscribed to
  • unsubs: The list of subscriptions that were unsubscribed from
{
    "stream":"v1.book.s",
    "subs":["BTC_USDT_Perp@500-100-10"],
    "unsubs":[]
}

In the case of an error, the following response will be returned:

  • code: The error code
  • message: The error message
  • status: The HTTP status code
{
    "code":3001,
    "message":"Stream handler not found",
    "status":400
}

Feed Structure

For each WebSocket stream, users may subscribe to multiple feeds. Each stream defines its own feed structure, which is documented on the relevant page. However, they all share the same underlying structure.

Firstly, feeds are broken down into primary@secondary selector pairs.

  • `primary` is used to determine the type of streaming data received.
  • `secondary` is used to determine the format/subtype of the streaming data received.

When subscribing to the same primary selector again, the previous secondary selector will be replaced.

eg. If previously subcribing to "BTC_USDT_Perp@500-100-10" and then subscribing to "BTC_USDT_Perp@500-1-10", the subscribe response will return.

{
    "stream":"v1.book.s",
    "subs":["BTC_USDT_Perp@500-1-10"],
    "unsubs":["BTC_USDT_Perp@500-100-10"]
}

Within each primary or secondary selector, fields are separated by -, and ordered by the schema definition.

Feed Data Stream

The feed data stream will return a continuous stream of JSON objects. It has the following structure:

  • stream: The stream that the data is from
  • selector: The selector that the data is from
  • sequence_number: This increases by one for each feed object published in the `stream`/`selector` pair. If the number `jumps`, it indicates data loss.
  • feed: The feed data object. Different for each stream.
{
    "stream": "v1.book.s",
    "selector": "BTC_USDT_Perp@500-100-10",
    "sequence_number": "872634876",
    "feed": {}
}

Event Time

All feed data is published with an event_time timestamp (in unix nanoseconds). This timestamp is stamped by our core cluster, and is guaranteed to be consistent across all services and nodes. For All Streams, other than MiniTicker raw streams, event time is a globally consistent unique identifier for a message. ie. All connections via WebSocket/REST can agree that a message is the same via its event_time.

Sequence Number

Sequence Numbers are stamped at the gateway level. Which means that it only has relevance within a single websocket connection, and nothing more. It helps you to guarantee that you received the right number of snapshot updates, and did not miss any delta updates.

  • All snapshot payloads will have a sequence number of `0`. All delta payloads will have a sequence number of `1+`. So its easy to distinguish between snapshots, and deltas
  • Num snapshots returned in JSON RPC Response (per stream): You can ensure that you received the right number of snapshots
  • First sequence number returned in JSON RPC Response (per stream): You can ensure that you received the first stream, without gaps from snapshots
  • Sequence numbers should always monotonically increase by `1`. If it decreases, or increases by more than `1`. Please reconnect
  • Duplicate sequence numbers are possible due to network retries. If you receive a duplicate, please ignore it, or idempotently re-update it.