GeminiGemini
SandboxGet API key
  • Crypto Trading
  • Prediction Markets
Resources
  • Changelog

© 2026 Gemini Space Station, Inc.

Gemini Crypto Exchange LogoGemini Crypto Exchange Logo

Market Data v1 (Archived)

This documentation is archived for reference only. These APIs have been replaced by the new WebSocket API. Start new integrations with the new WebSocket API.

WebSocket API v1 Overview

Introduction

Using WebSockets provides several advantages:

  • Receive notifications in real time
  • Reduce the amount of data you have to transfer over the network
  • Reduce latency introduced by polling interval

For example, to keep track of your orders, you might be requesting the Get Active Orders endpoint every five seconds. Using the private Order Events API, you would subscribe once and receive real time notifications of all order activity.

WebSocket Protocol Resources

  • About HTML5 WebSocket
  • RFC 6455 The WebSocket Protocol

Requests

Both public and private WebSocket API requests begin with a GET request that includes headers asking for an upgrade to the WebSocket protocol. The private API WebSocket request also includes the standard private API headers.

Public API Request Headers

Code
GET wss://api.gemini.com/v1/marketdata/BTCUSD Connection: Upgrade Upgrade: websocket Sec-WebSocket-Key: uRovscZjNol/umbTt5uKmw== Sec-WebSocket-Version: 13

Private API Request Headers

Code
GET wss://api.gemini.com/v1/order/events Connection: Upgrade Upgrade: websocket Sec-WebSocket-Key: uRovscZjNol/umbTt5uKmw== Sec-WebSocket-Version: 13 X-GEMINI-APIKEY: qOfnZJDZTTBsxdM3bVRP X-GEMINI-PAYLOAD: eyJyZXF1ZXN0IjoiL3YxL29yZGVyL2V2ZW50cyIsIm5vbmNlIjoxNDc3OTYzMjQwNzQxMDgzMzA3fQ== X-GEMINI-SIGNATURE: 88cd6f391d8f920a76a2060d613b519a8e8b4b3fb5bff089ea826d49ac73888bd479c0c2e2062ba60ba7afbe273132e3

Private API Invocation

Gemini uses API keys to allow access to private APIs. You can obtain these by logging on and creating a key in Settings/API. This will give you both an "API Key" that will serve as your user name, and an "API Secret" that you will use to sign messages.

All requests must contain a nonce, a number that will never be repeated and must increase between requests. This is to prevent an attacker who has captured a previous request from simply replaying that request. We recommend using a timestamp at millisecond or higher precision.

Payload

The payload of the requests will be a JSON object. Rather than being sent as the body of the POST request, it will be base-64 encoded and stored as a header in the request.

Authenticated APIs do not submit their payload as POSTed data, but instead put it in the X-GEMINI-PAYLOAD header.

Headers

HeaderValue
Content-Length0
Content-Typetext/plain
X-GEMINI-APIKEYYour Gemini API key
X-GEMINI-PAYLOADThe base64-encoded JSON payload
X-GEMINI-SIGNATUREhex(HMAC_SHA384(base64(payload), key=api_secret))
Cache-Controlno-cache

Example

Code
{ "request": "/v1/order/events", "nonce": <nonce> }

Base64 encode, then sign with HMAC-SHA384:

Code
import base64, hmac, hashlib, json, time gemini_api_key = "mykey" gemini_api_secret = "1234abcd".encode() payload = {"request": "/v1/order/events", "nonce": time.time()} encoded_payload = json.dumps(payload).encode() b64 = base64.b64encode(encoded_payload) signature = hmac.new(gemini_api_secret, b64, hashlib.sha384).hexdigest()

Roles

Gemini uses a role-based system for private API endpoints so that you can separate privileges for your API keys.

EndpointURITraderFund ManagerAuditor
Order Events/v1/order/eventsYesNoYes

Responses

If successful, API requests will return an HTTP 101 Switching Protocols code in the response headers:

Code
HTTP/1.1 101 Switching Protocols Connection: upgrade Upgrade: websocket Sec-WebSocket-Accept: wEV5o5orKGO27qATSTLczquY3EH=

Then the HTTP connection will be replaced by a WebSocket connection.


Data Types

TypeDescription
stringA simple quoted string, following standard JSON rules.
decimalA decimal value, encoded in a JSON string.
timestampThe number of seconds since 1970-01-01 UTC. Use timestampms when available.
timestampmsThe number of milliseconds since 1970-01-01 UTC. Transmitted as a JSON number.
integerA whole number, transmitted as a JSON number.
booleanA JSON boolean, the literal string true or false.
arrayA JSON array.

Timestamps

The timestamp data type describes a date and time as a whole number in Unix Time format.

Gemini strongly recommends using milliseconds instead of seconds for timestamps.

Timestamp formatExampleSupported request type
whole number (seconds)1495127793GET, POST
string (seconds)"1495127793"POST only
whole number (milliseconds)1495127793000GET, POST
string (milliseconds)"1495127793000"POST only

In responses, timestamp denotes seconds and timestampms denotes milliseconds since 1970-01-01 UTC.

Basis Points

Fees are calculated as a fraction of the notional value of each trade (price x amount) in basis points ("bps"), which represent 1/100th of a percent. For example, a fee of 25 bps means 0.25% of the denominated value.


Sequence Numbers

Events and heartbeats contain a socket_sequence number:

  1. WebSocket connection is established
  2. Optional subscription acknowledgement
  3. First event with socket_sequence set to 0
  4. Each subsequent message increases the sequence by one

If you see a gap in the sequence number, disconnect and reconnect.

Each time you reconnect, the sequence number resets to zero. Multiple WebSocket connections each have separate sequence numbers.


Rate Limits

To prevent abuse, Gemini imposes rate limits on incoming requests.

For public WebSocket APIs, we recommend that you do not exceed 1 request per symbol per minute.


Error Codes

If a response is in error, the HTTP response code will reflect this, and a JSON body will be returned:

Code
{ "result": "error", "reason": "BadNonce", "message": "Out-of-sequence nonce <1234> precedes previously used nonce <2345>" }

HTTP Status Codes

HTTP StatusMeaning
200Request was successful
30xAPI entry point has moved, see Location header
400Market not open, or the request was malformed
403The API key is missing the role necessary to access this endpoint
404Unknown API entry point or Order not found
406Insufficient Funds
429Rate Limiting was applied
500The server encountered an error
502Technical issues are preventing the request from being satisfied
503The exchange is down for maintenance

Error Reasons

ReasonMeaning
ClientOrderIdTooLongThe Client Order ID must be under 100 characters
ConflictingOptionsNew orders using a combination of order execution options are not supported
EndpointMismatchThe request was submitted to an endpoint different than the one in the payload
InsufficientFundsThe order was rejected because of insufficient funds
InvalidJsonThe JSON provided is invalid
InvalidNonceThe nonce was not greater than the previously used nonce
InvalidOrderTypeAn unknown order type was provided
InvalidPriceFor new orders, the price was invalid
InvalidQuantityA negative or otherwise invalid quantity was specified
InvalidSideFor new orders, an invalid side was specified
InvalidSignatureThe signature did not match the expected signature
InvalidSymbolAn invalid symbol was specified
MarketNotOpenThe order was rejected because the market is not accepting new orders
MissingApikeyHeaderThe X-GEMINI-APIKEY header was missing
MissingPayloadHeaderThe X-GEMINI-PAYLOAD header was missing
MissingSignatureHeaderThe X-GEMINI-SIGNATURE header was missing
MissingRoleThe API key does not have the required role assigned
OrderNotFoundThe order specified was not found
RateLimitRequests were made too frequently
SystemWe are experiencing technical issues

Sandbox

Gemini's sandbox site is an instance of the Gemini Exchange that offers full exchange functionality using test funds.

ResourceURL
Websitehttps://exchange.sandbox.gemini.com
REST APIhttps://api.sandbox.gemini.com
WebSocket Feedwss://api.sandbox.gemini.com
Documentationhttps://docs.sandbox.gemini.com

Go to the sandbox site to register for a test account. Your account will automatically be credited with USD, BTC, ETH, BCH, LTC, OXT, LINK, BAT and DAI.

Two Factor Authentication: 2FA is enabled by default. To disable for automated testing, set a cookie or HTTP header named GEMINI-SANDBOX-2FA and enter 9999999 as the 2FA code.


Client Order ID

Client order ID is a client-supplied order identifier that Gemini will echo back in all subsequent messages about that order. Gemini strongly recommends supplying client_order_id when placing orders.

Your client order IDs are only visible to Gemini and you. They should be unique per trading session and must match: [:\-_\.#a-zA-Z0-9]{1,100}.

CharactersDescriptionASCII Codes
A-ZUppercase letters65-90
a-zLowercase letters97-122
0-9Digits48-57
# - . : _Special characters35, 45, 46, 58, 95

Market Data v1

Market data is a public API that streams all the market data on a given symbol.

WebSocket Request

wss://api.gemini.com/v1/marketdata/:symbol

URL Parameters

ParameterRequiredDefaultDescription
heartbeatNofalseSet to true to receive a heartbeat every 5 seconds
top_of_bookNofalseIf true, receive top of book only (bids and offers)
bidsNotrueInclude bids in change events
offersNotrueInclude asks in change events
tradesNotrueInclude trade events

The semantics of entry type filtering:

  • To be excluded from change events, an entry type must be explicitly flagged false
  • If no filtering parameters are included, all entry types will appear

top_of_book has no meaning and initial book events are empty when only trades is specified.

Response

Each frame contains a JSON message with the following format:

FieldTypeDescription
typestringheartbeat or update
socket_sequenceintegerMonotonic increasing sequence number

Messages of type update also include:

FieldTypeDescription
eventIdintegerMonotonically increasing sequence number for changes
eventsarrayOrder book changes or trade indications
timestamptimestampTimestamp in seconds (use timestampms instead)
timestampmstimestampmsTimestamp in milliseconds

All elements of events share:

FieldTypeDescription
typestringEither trade or change

Change Event

FieldTypeDescription
pricedecimalPrice of this order book entry
sidestringbid or ask
reasonstringplace, trade, cancel, or initial
remainingdecimalQuantity remaining at this price level
deltadecimalQuantity changed (may be negative)

Every trade triggers a message with entries of both types trade and change.

To keep an up-to-date order book, watch for {"type": "change"} events and update the price level at price with the amount at remaining.

Trade Event

FieldTypeDescription
pricedecimalExecution price
amountdecimalAmount traded
makerSidestringbid or ask

Examples

Code
import ssl import websocket def on_message(ws, message): print(message) ws = websocket.WebSocketApp( "wss://api.gemini.com/v1/marketdata/BTCUSD", on_message=on_message) ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE})

Initial Response (top of book)

Code
{ "type": "update", "eventId": 5375461993, "socket_sequence": 0, "events": [ { "type": "change", "reason": "initial", "price": "3641.61", "delta": "0.83372051", "remaining": "0.83372051", "side": "bid" }, { "type": "change", "reason": "initial", "price": "3641.62", "delta": "4.072", "remaining": "4.072", "side": "ask" } ] }

When a trade occurs

Code
{ "type": "update", "eventId": 5375547515, "timestamp": 1547760288, "timestampms": 1547760288001, "socket_sequence": 15, "events": [ { "type": "trade", "tid": 5375547515, "price": "3632.54", "amount": "0.1362819142", "makerSide": "ask" } ] }

Heartbeat

Code
{ "type": "heartbeat", "socket_sequence": 30 }
Last modified on April 17, 2026
On this page
  • Introduction
    • WebSocket Protocol Resources
  • Requests
    • Public API Request Headers
    • Private API Request Headers
  • Private API Invocation
    • Payload
    • Headers
    • Example
  • Roles
  • Responses
  • Data Types
    • Timestamps
    • Basis Points
  • Sequence Numbers
  • Rate Limits
  • Error Codes
    • HTTP Status Codes
    • Error Reasons
  • Sandbox
  • Client Order ID
JSON
JSON
JSON
JSON
JSON