OAuth 2.0
In addition to the API key methods described in private APIs, Gemini supports OAuth 2.0 flows and adheres to the OAuth 2.0 Standards. Both authorization code and implicit OAuth flows are supported, however use of authorization code flows is strongly recommended for most use cases because of enhanced security and the ability to support features such as refresh tokens.
The first step in using Gemini OAuth is to create a new OAuth application which you can do via API Settings. You will be asked for some basic information including a name, description, background information, logo, and the scopes that you are requesting access to. We will provide you a client_id
and a client_secret
which are used to identify and secure your app.
Once your app is registered it will be reviewed by Gemini, and then set live for use. You may also follow the same process in our Sandbox Environment to build a test integration.
Please email trading@gemini.com with any questions. We will provide you a client_id
and a client_secret
. Your client_id
will be used in all your requests to identify your app, and client_secret
must be sent in all POST requests
Instead of API Keys OAuth 2.0 uses access tokens and, if using the authorization code grant flow, refresh tokens. Access tokens are short-lived (24 hour expiration) and are used in Gemini API calls while refresh tokens don't expire and are used solely to generate new access tokens.
Authorization Code Grant Flow
The OAuth 2.0 authorization code grant flow involves the user being directed to an authorization server which returns an authorization code that may then be exchanged for access and refresh tokens. Access tokens are short-lived (24 hour expiration) and are used as authentication against Gemini APIs, while refresh tokens never expire and are used to regenerate access tokens.
Authorization Request
Users should first be redirected to Gemini to authorize access to your application. The user will be prompted to login using a Gemini OAuth window.
GET https://exchange.gemini.com/auth
Example authorization request:
GET https://exchange.gemini.com/auth?client_id=my_id&response_type=code&redirect_uri=www.example.com/redirect&state=82350325&scope=balances:read,orders:create
URL Parameters
Parameter | Type | Description |
---|---|---|
client_id | string | Unique id of your application. This is provided in your API settings |
response_type | string | The literal string "code" |
redirect_uri | string | The URL users should be returned to when they authorize. Note, this URL must be included in your list of approved redirect_uris in your app registration |
state | string | A random string that will be returned to you in the response. |
scope | string | A comma separated list of scopes corresponding to the access you're requesting for your application. Note, these scopes must be included in your list of scopes in your app registration |
Authorization Response
Example
redirect_uri
response after user login
https://www.example.com/redirect?code=90123465-86ee-44ef-b4e3-835cc89bc8a3&state=82350325
On successful authorization Gemini will redirect your user to the redirect_uri
you supplied with additional parameters code
and state
. The parameter state
should match the state
you provided, otherwise you should not trust the response. code
is a temporary code which you will then use to obtain access and refresh tokens.
Token Request
Once you have received a code
you can exchange it for access and refresh tokens.
POST https://exchange.gemini.com/auth/token
Parameter | Type | Description |
---|---|---|
client_id | string | Unique id of your application. This is provided in your API settings |
client_secret | string | Secret of your application. This is provided when you first register an app in API settings |
code | string | The code you received from the authorization request |
redirect_uri | string | This must match the redirect_uri provided in the authorization request |
grant_type | string | The literal string "authorization_code" |
Example Token Request
{
"client_id": "my_id",
"client_secret": "my_secret",
"code": "90123465-86ee-44ef-b4e3-835cc89bc8a3",
"redirect_uri": "www.example.com/redirect",
"grant_type": "authorization_code"
}
Token Response
Field | Type | Description |
---|---|---|
access_token | string | A short-lived token to use in API call authentication. Is valid until the expires_in time reaches 0 |
refresh_token | string | A refresh token to be used to generate new access tokens |
token_type | string | The literal string "bearer" |
scope | string | The scopes the access token will have access to |
expires_in | integer | The lifetime in seconds of the access token, as measured in seconds from the current time |
Example Token Response
{
"access_token": "d9af2411-3e85-41bb-89f4-cf53750f04df",
"refresh_token": "215c5a89-6df7-457b-ba0b-70695da8c91f",
"token_type": "Bearer",
"scope": "balances:read,orders:create",
"expires_in": 86399
}
Using Refresh Tokens
The access token you receive will be relatively short-lived (default 24 hours). Once an access token has expired you can use your refresh token to generate a new access token. Refresh tokens never expire, however they are one-time use only as your request for a new access token will also return a new refresh token.
Getting a new access token is similar to getting the initial access and refresh tokens with slightly different parameters
Token Request
POST https://exchange.gemini.com/auth/token
Example Token Request
{
"client_id": "my_id",
"client_secret": "my_secret",
"refresh_token": "215c5a89-6df7-457b-ba0b-70695da8c91f",
"grant_type":"refresh_token"
}
Parameter | Type | Description |
---|---|---|
client_id | string | Unique id of your application |
client_secret | string | Secret of your application. This is provided when you first register an app in [API settings][API Settings] |
refresh_token | string | Your refresh token |
grant_type | string | The literal string "refresh_token" |
Token Response
The response is the same as the initial token response – it will contain a new access token to query APIs and a new refresh token for when the access token expires.
Parameter | Type | Description |
---|---|---|
access_token | string | A short-lived token to use in API call authentication |
refresh_token | string | A refresh token to be used to generate new access tokens |
token_type | string | The literal string "bearer" |
scope | string | The scopes the access token will have access to |
expires_in | integer | The lifetime in seconds of the access token, as measured in seconds from the current time |
Example Token Response
{
"access_token": "c5e9459d-dc6f-4567-bce4-050ec965f22e",
"expires_in": 86399,
"scope": "balances:read,orders:create",
"refresh_token": "ce0f14af-74dd-4767-a4e7-286e98b944c1",
"token_type": "Bearer"
}
Implicit Grant Flow
In addition to the authorization code flow, Gemini also supports the OAuth 2.0 implicit grant flow. This is a simplified version of the authorization code flow and is not recommended for most applications. This OAuth flow is not available by default, please reach out to trading@gemini.com to request access to the implicit grant flow.
When the access_token
expires you must request a new one using either the implicit flow or authorization code flow.
Send request to following URL with URL parameters
GET https://exchange.gemini.com/auth
First direct users to Gemini like the example below
GET https://exchange.gemini.com/auth?response_type=token&client_id=my_id&redirect_uri=https://example.com/redirect?scope=Trader&state=7j87
URL Parameters
Parameter | Type | Description |
---|---|---|
response_type | string | The literal string "token" |
client_id | string | Unique id of your application. This is provided in your API settings |
redirect_uri | string | The URL users should be returned to when they authorize. Note, this URL must be included in your list of approved redirect_uris in your app registration |
state | string | A random string that will be returned to you in the response. |
scope | string | A comma separated list of scopes corresponding to the access you're requesting for your application. Note, these scopes must be included in your list of scopes in your app registration |
Users will then be sent to Gemini login with their credentials. Once they do they will be sent to the redirect_uri
provided.
Authorization Response (URL Parameters)
Example
redirect_uri
response after user login
https://example.com/redirect#access_token=3b7661f0-f156-498a-ad17-0fa4025ec907&state=7j87&token_type=bearer&scope=Trader&expires_in=83534
On successful authorization Gemini will redirect your user to the redirect_uri
you supplied with additional parameters code
and state
. The parameter state
should match the state
you provided, otherwise you should not trust the response. access_token
is the access token which you will use to make API calls on behalf of the user.
Field | Type | Description |
---|---|---|
access_token | string | A short-lived token to use in API call authentication. Is valid until the expires_in time reaches 0 |
token_type | string | The literal string "bearer" |
scope | string | The scopes the access token will have access to |
expires_in | integer | The lifetime in seconds of the access token, as measured in seconds from the current time |
Using Access Tokens
Once you have an access token you can use it to call any Gemini API.
Most of the examples for the private APIs in these docs make use of API keys and corresponding headers, to use an access token simply update your header:
Header | Description |
---|---|
Authorization | The literal string "Bearer " concatenated to your temporary access_token |
X-GEMINI-PAYLOAD | The base64-encoded JSON payload (the payloads on OAuth do not require a nonce) |
import requests
import json
import base64
url = "https://api.gemini.com/v1/mytrades"
access_token = "Bearer d9af2411-3e85-41bb-89f4-cf53750f04df"
payload = {
"request": "/v1/mytrades",
"symbol": "btcusd"
}
encoded_payload = json.dumps(payload).encode()
b64 = base64.b64encode(encoded_payload)
request_headers = {
"Authorization": access_token,
"X-GEMINI-PAYLOAD": b64
}
response = requests.post(url,
data=None,
headers=request_headers,
verify=False)
my_trades = response.json()
$ curl -X POST https://api.gemini.com/v1/mytrades \
-H 'Authorization: Bearer d9af2411-3e85-41bb-89f4-cf53750f04df' \
-H 'X-GEMINI-PAYLOAD: eyJyZXF1ZXN0IjogIi92MS9teXRyYWRlcyIsICJzeW1ib2wiOiAiYnRjdXNkIn0='
import requests
import json
import base64
url = "https://api.gemini.com/v1/orders/history"
access_token = "Bearer d9af2411-3e85-41bb-89f4-cf53750f04df"
payload = {
"request": "/v1/orders/history",
"symbol": "btcusd"
}
encoded_payload = json.dumps(payload).encode()
b64 = base64.b64encode(encoded_payload)
request_headers = {
"Authorization": access_token,
"X-GEMINI-PAYLOAD": b64
}
response = requests.post(url,
data=None,
headers=request_headers,
verify=False)
my_orders = response.json()
$ curl -X POST https://api.gemini.com/v1/orders/history \
-H 'Authorization: Bearer d9af2411-3e85-41bb-89f4-cf53750f04df' \
-H 'X-GEMINI-PAYLOAD: eyJyZXF1ZXN0IjogIi92MS9teXRyYWRlcyIsICJzeW1ib2wiOiAiYnRjdXNkIn0='
OAuth Scopes
Gemini uses a role-based system for its API. All OAuth applications are limited to the scopes in the following chart:
Endpoint | URI | Scope |
---|---|---|
Get Deposit Addresses | /v1/addresses/:network |
addresses:read, addresses:create |
New Deposit Address | /v1/deposit/:network/newAddress |
addresses:create |
Create Approved Address | /v1/approvedAddresses/:network/request |
addresses:create |
View Approved Address List | /v1/approvedAddresses/account/:network |
addresses:read |
Remove Address from Approved Address List | /v1/approvedAddresses/:network/remove |
addresses:create |
Get Available Balances | /v1/balances |
balances:read |
Get Notional Balances | v1/notionalbalances/:currency |
balances:read |
Add A Bank | /v1/payments/addbank |
banks:create |
Add A Bank CAD | /v1/payments/addbank/cad |
banks:create |
View Payment Methods | /v1/payments/methods |
banks:read, banks:create |
New Clearing Order | /v1/clearing/new |
clearing:create |
Cancel Clearing Order | /v1/clearing/cancel |
clearing:create |
Confirm Clearing Order | /v1/clearing/confirm |
clearing:create |
Clearing Order Status | /v1/clearing/status |
clearing:read |
Clearing Order List | /v1/clearing/list |
clearing:read |
Clearing Broker List | /v1/clearing/broker/list |
clearing:read |
Clearing Trades | /v1/clearing/trades |
clearing:read |
Withdraw Crypto Funds | /v1/withdraw/:currency |
crypto:send |
Get Past Trades | /v1/mytrades |
history:read |
Get Orders History | /v1/orders/history |
history:read |
Get Notional Volume | /v1/notionalvolume |
history:read |
Get Trade Volume | /v1/tradevolume |
history:read |
Transfers | /v1/transfers |
history:read |
Custody Account Fees | /v1/custodyaccountfees |
history:read |
New Order | /v1/order/new |
orders:create |
Cancel Order | /v1/order/cancel |
orders:create |
Cancel All Session Orders | /v1/order/cancel/session |
orders:create |
Cancel All Active Orders | /v1/order/cancel/all |
orders:create |
Wrap Order | /v1/wrap/:symbol |
orders:create |
Get Instant Quote | /v1/instant/quote/:side/:symbol |
orders:create |
Execute Instant Order | /v1/instant/execute |
orders:create |
Order Status | /v1/order/status |
orders:read |
Get Active Orders | /v1/orders |
orders:read |
Account Detail | /v1/account |
account:read |
API keys use different roles for to access Gemini APIs. Please see roles for descriptions of each role and scope for API keys.
Revoke OAuth Token
The access_token
may be revoked at any time by using v1/oauth/revokeByToken
. Once a token is revoked or expires, it can no longer be used to make requests.
This endpoint is only available using an access_token
and will revoke the token used to make the request.
HTTP Request
POST https://api.gemini.com/v1/oauth/revokeByToken
Parameters
No fields are expected in this request, other than the request name.
Parameter | Type | Description |
---|---|---|
request | string | The literal string "/v1/oauth/revokeByToken" |
Sample payload
json { "request": "/v1/oauth/revokeByToken" }
$ curl -X POST https://api.gemini.com/v1/oauth/revokeByToken \
-H 'Authorization: Bearer d9af2411-3e85-41bb-89f4-cf53750f04df' \
-H 'X-GEMINI-PAYLOAD: eyJyZXF1ZXN0IjogIi92MS9vYXV0aC9yZXZva2VCeVRva2VuIn0='
Response
An array that indicates the access_token
has been revoked.
Field | Type | Description |
---|---|---|
message | string | A message that indicates the token has been revoked for the account |
{
"message": "OAuth tokens and codes have been revoked for 00000000-0000-0000-0000-000000000000 on your account."
}
Revision History
Date | Notes |
---|---|
2020/08/20 | Initial OAuth documentation |
- Trust is Our Product™
- For trademarks and patents, please see the Legal Notice.
- NMLS #1518126
- © Copyright 2022 Gemini Trust Company, LLC.