# OAuth 2.0


In addition to the API key methods described in [private APIs](/authentication/api-key#private-api-invocation), Gemini supports OAuth 2.0 and adheres to the [OAuth 2.0 Standards](https://oauth.net/2/). Gemini uses the authorization code grant flow with refresh tokens; all authorization requests use `response_type=code`.

The first step in using Gemini OAuth is to create a new OAuth application, which you can do via [API Settings](https://exchange.gemini.com/settings/api). You will be asked for some basic information including a name, description, background information, logo, and the [scopes](/authentication/oauth#oauth-scopes) you are requesting access to.

When you create an app you choose its client type, and that choice is permanent:

- A **confidential client** is issued a `client_id` and a `client_secret`. This is the default. Use it when your app runs on a server you control and can keep the secret private.
- A **public client** is issued a `client_id` only — no secret. Use it for apps that cannot keep a secret confidential, such as native mobile apps, desktop apps, and single-page apps. Public clients must use [PKCE](#public-clients-and-pkce) on the authorization code flow.

Your `client_id` identifies your app in every request. A confidential client also sends its `client_secret` in all `POST` requests; a public client never sends a secret and uses PKCE instead. You cannot change a client's type after it is created, so pick the one that matches where your app runs.

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](https://exchange.sandbox.gemini.com/settings/api) to build a test integration. Please email trading@gemini.com with any questions.

Instead of API keys, OAuth 2.0 uses access tokens and 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`



:::note
Example authorization request (confidential client):
:::

`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`

:::note
Example authorization request (public client — adds the PKCE `code_challenge` and `code_challenge_method`):
:::

`GET https://exchange.gemini.com/auth?client_id=my_id&response_type=code&redirect_uri=http://127.0.0.1:51234/callback&state=82350325&scope=balances:read,orders:create&code_challenge=5S_YsMh19iBDX5plIVTXdtF3iJCbJ388EEVd5CVlWxU&code_challenge_method=S256`

### URL Parameters

<table>
   <thead>
      <tr>
         <th>Parameter</th>
         <th>Type</th>
         <th>Description</th>
      </tr>
   </thead>
   <tbody>
      <tr>
         <td>client_id</td>
         <td>string</td>
         <td>Unique id of your application. This is provided in your [API settings](https://exchange.gemini.com/settings/api)</td>
      </tr>
      <tr>
         <td>response_type</td>
         <td>string</td>
         <td>The literal string "code"</td>
      </tr>
      <tr>
         <td>redirect_uri</td>
         <td>string</td>
         <td>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</td>
      </tr>
      <tr>
         <td>state</td>
         <td>string</td>
         <td>A random string that will be returned to you in the response. Required (and must be non-empty) for public clients to protect against CSRF; strongly recommended for confidential clients.</td>
      </tr>
      <tr>
         <td>scope</td>
         <td>string</td>
         <td>A comma separated list of [scopes](#oauth-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</td>
      </tr>
      <tr>
         <td>code_challenge</td>
         <td>string</td>
         <td>Required for public clients. The PKCE code challenge: `BASE64URL-no-padding(SHA-256(code_verifier))`. Always 43 characters for the `S256` method. See [Public Clients and PKCE](#public-clients-and-pkce)</td>
      </tr>
      <tr>
         <td>code_challenge_method</td>
         <td>string</td>
         <td>Required for public clients. The literal string "S256". `plain` is not accepted</td>
      </tr>
   </tbody>
</table>

## Authorization Response

:::note
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.

### Authorization Token Request
Once you have received a `code` you can exchange it for access and refresh tokens.

`POST https://exchange.gemini.com/auth/token`

<table>
   <thead>
      <tr>
         <th>Parameter</th>
         <th>Type</th>
         <th>Description</th>
      </tr>
   </thead>
   <tbody>
      <tr>
         <td>client_id</td>
         <td>string</td>
         <td>Unique id of your application. This is provided in your [API settings](https://exchange.gemini.com/settings/api)</td>
      </tr>
      <tr>
         <td>client_secret</td>
         <td>string</td>
         <td>Secret of your application, provided when you register a confidential client in [API settings](https://exchange.gemini.com/settings/api). Confidential clients only — public clients must not send this, and a request that includes it will fail</td>
      </tr>
      <tr>
         <td>code</td>
         <td>string</td>
         <td>The code you received from the authorization request</td>
      </tr>
      <tr>
         <td>redirect_uri</td>
         <td>string</td>
         <td>This must match the `redirect_uri` provided in the authorization request</td>
      </tr>
      <tr>
         <td>grant_type</td>
         <td>string</td>
         <td>The literal string "authorization_code"</td>
      </tr>
      <tr>
         <td>code_verifier</td>
         <td>string</td>
         <td>Required for public clients. The original `code_verifier` you generated before the authorization request (43–128 characters from `[A-Za-z0-9-._~]`). Gemini hashes it and compares it to the `code_challenge` you sent</td>
      </tr>
   </tbody>
</table>

:::note
Example token request (confidential client — sends `client_secret`):
:::

```json
{
    "client_id": "my_id",
    "client_secret": "my_secret",
    "code": "90123465-86ee-44ef-b4e3-835cc89bc8a3",
    "redirect_uri": "www.example.com/redirect",
    "grant_type": "authorization_code"
}
```

:::note
Example token request (public client — sends `code_verifier`, no `client_secret`):
:::

```json
{
    "client_id": "my_id",
    "code": "90123465-86ee-44ef-b4e3-835cc89bc8a3",
    "redirect_uri": "http://127.0.0.1:51234/callback",
    "grant_type": "authorization_code",
    "code_verifier": "M25iVXpKU3puUjFaYWg3T1NDTDQtcW1ROUY5YXlwalNoc0hhakx-fkdq"
}
```

### Authorization Token Response

<table>
   <thead>
      <tr>
         <th>Field</th>
         <th>Type</th>
         <th>Description</th>
      </tr>
   </thead>
   <tbody>
      <tr>
         <td>access_token</td>
         <td>string</td>
         <td>A short-lived token to use in API call authentication. Is valid until the `expires_in` time reaches 0</td>
      </tr>
      <tr>
         <td>refresh_token</td>
         <td>string</td>
         <td>A refresh token to be used to generate new access tokens</td>
      </tr>
      <tr>
         <td>token_type</td>
         <td>string</td>
         <td>The literal string "bearer"</td>
      </tr>
      <tr>
         <td>scope</td>
         <td>string</td>
         <td>The [scopes](#oauth-scopes) the access token will have access to</td>
      </tr>
      <tr>
         <td>expires_in</td>
         <td>integer</td>
         <td>The lifetime in seconds of the access token, as measured in seconds from the current time</td>
      </tr>
   </tbody>
</table>

:::note
Example Token Response
:::

```json
{
    "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
}
```

## Public Clients and PKCE

A public client is an OAuth app that runs somewhere it cannot keep a secret — a native mobile app, a desktop app, or a single-page app. Because the code ships to the user's device or browser, anyone can read it, so there is no `client_secret` to protect the token exchange. Public clients close that gap with PKCE (Proof Key for Code Exchange, [RFC 7636](https://datatracker.ietf.org/doc/html/rfc7636)).

PKCE is required for every public client, and it only works with the authorization code flow. Your app generates a one-time secret before it starts, sends only a hash of that secret when it asks for an authorization code, and reveals the original secret when it exchanges the code for tokens. Gemini hashes what you reveal and checks it against the hash you sent earlier. An attacker who intercepts the authorization code cannot use it, because they never saw the original secret.

### How PKCE works

1. **Generate a `code_verifier`.** A high-entropy random string of 43–128 characters using only `A-Z`, `a-z`, `0-9`, `-`, `.`, `_`, `~` ([RFC 7636 §4.1](https://datatracker.ietf.org/doc/html/rfc7636#section-4.1)).
2. **Derive the `code_challenge`.** `BASE64URL-no-padding(SHA-256(code_verifier))` — exactly 43 characters for `S256`.
3. **Send the challenge on the authorization request.** On `GET https://exchange.gemini.com/auth`, include `code_challenge`, `code_challenge_method=S256`, and a non-empty `state`. `S256` is the only method Gemini accepts; `plain` is rejected.
4. **Send the verifier on the token request.** On `POST https://exchange.gemini.com/auth/token`, include the original `code_verifier`. Do **not** include a `client_secret`. Gemini hashes the verifier and compares it to the challenge from step 3.

Public clients must also send a non-empty `state` on the authorization request. For confidential clients `state` is strongly recommended; for public clients it is required, because there is no secret to anchor the request and `state` is your protection against CSRF. Compare the `state` in the response to the value you sent, and reject the response if they don't match.

Refresh works the same way for a public client as for a confidential one, with one difference: omit the `client_secret`. There is no `code_verifier` on a refresh request.

**Redirect URIs for public clients.** To support native and desktop apps ([RFC 8252](https://datatracker.ietf.org/doc/html/rfc8252)), a public client may register an `http` loopback redirect URI — `http://localhost`, `http://127.0.0.1`, or `http://[::1]` — and the port may vary at runtime, so an ephemeral port chosen by the OS will be accepted. Loopback redirect URIs must use `http` (not `https`) and must not include user info. Every other (non-loopback) redirect URI must match your registered URI exactly.

:::note
Generating a `code_verifier` and deriving the `S256` `code_challenge` in Python:
:::

```python
import hashlib
import base64
import secrets

# 1. High-entropy code_verifier (token_urlsafe uses the unreserved set; 64 bytes -> ~86 chars)
code_verifier = secrets.token_urlsafe(64)

# 2. code_challenge = BASE64URL-no-padding( SHA-256( code_verifier ) )
digest = hashlib.sha256(code_verifier.encode("ascii")).digest()
code_challenge = base64.urlsafe_b64encode(digest).rstrip(b"=").decode("ascii")

# Send code_challenge + code_challenge_method=S256 on the authorization request,
# then send code_verifier on the token request.
```

## 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

### Refresh Token Request

`POST https://exchange.gemini.com/auth/token`

:::note
Example Token Request
:::

```json
{
    "client_id": "my_id",
    "client_secret": "my_secret",
    "refresh_token": "215c5a89-6df7-457b-ba0b-70695da8c91f",
    "grant_type":"refresh_token"
}
```

<table>
   <thead>
      <tr>
         <th>Parameter</th>
         <th>Type</th>
         <th>Description</th>
      </tr>
   </thead>
   <tbody>
      <tr>
         <td>client_id</td>
         <td>string</td>
         <td>Unique id of your application</td>
      </tr>
      <tr>
         <td>client_secret</td>
         <td>string</td>
         <td>Secret of your application. This is provided when you first register an app in [API settings](https://exchange.gemini.com/settings/api)</td>
      </tr>
      <tr>
         <td>refresh_token</td>
         <td>string</td>
         <td>Your refresh token</td>
      </tr>
      <tr>
         <td>grant_type</td>
         <td>string</td>
         <td>The literal string "refresh_token"</td>
      </tr>
   </tbody>
</table>

### Refresh 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.

<table>
   <thead>
      <tr>
         <th>Parameter</th>
         <th>Type</th>
         <th>Description</th>
      </tr>
   </thead>
   <tbody>
      <tr>
         <td>access_token</td>
         <td>string</td>
         <td>A short-lived token to use in API call authentication</td>
      </tr>
      <tr>
         <td>refresh_token</td>
         <td>string</td>
         <td>A refresh token to be used to generate new access tokens</td>
      </tr>
      <tr>
         <td>token_type</td>
         <td>string</td>
         <td>The literal string "bearer"</td>
      </tr>
      <tr>
         <td>scope</td>
         <td>string</td>
         <td>The [scopes](#oauth-scopes) the access token will have access to</td>
      </tr>
      <tr>
         <td>expires_in</td>
         <td>integer</td>
         <td>The lifetime in seconds of the access token, as measured in seconds from the current time</td>
      </tr>
   </tbody>
</table>


:::note
Example Token Response
:::

```json
{
  "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"
}
```

## 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](/authentication/api-key#private-api-invocation), 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) |


```python
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()
```

```python
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()
```

## OAuth Scopes
Gemini uses a role-based system for its API. All OAuth applications are limited to the scopes in the following chart:

<table>
   <thead>
      <tr>
         <th>Endpoint</th>
         <th>URI</th>
         <th>Scope</th>
      </tr>
   </thead>
   <tbody>
      <tr>
         <td>[Get Deposit Addresses](/rest/fund-management#list-deposit-addresses)</td>
         <td>`/v1/addresses/:network`</td>
         <td>`addresses:read, addresses:create`</td>
      </tr>
      <tr>
         <td>[New Deposit Address](/rest/fund-management#create-new-deposit-address)</td>
         <td>`/v1/deposit/:network/newAddress`</td>
         <td>`addresses:create`</td>
      </tr>
      <tr>
         <td>[List Approved Addresses](/rest/fund-management#list-approved-addresses)</td>
         <td>`/v1/approvedAddresses/account/:network`</td>
         <td>`addresses:read`</td>
      </tr>
      <tr>
         <td>[Remove Approved Address](/rest/fund-management#remove-approved-address)</td>
         <td>`/v1/approvedAddresses/:network/remove`</td>
         <td>`addresses:create`</td>
      </tr>
      <tr>
         <td>[Get Available Balances](/rest/fund-management#get-available-balances)</td>
         <td>`/v1/balances`</td>
         <td>`balances:read`</td>
      </tr>
      <tr>
         <td>[Get Notional Balances](/rest/fund-management#get-notional-balances)</td>
         <td>`v1/notionalbalances/:currency`</td>
         <td>`balances:read`</td>
      </tr>
      <tr>
         <td>[Add A Bank](/rest/fund-management#add-bank)</td>
         <td>`/v1/payments/addbank`</td>
         <td>`banks:create`</td>
      </tr>
      <tr>
         <td>[Add A Bank CAD](/rest/fund-management#add-bank-cad)</td>
         <td>`/v1/payments/addbank/cad`</td>
         <td>`banks:create`</td>
      </tr>
      <tr>
         <td>[View Payment Methods](/rest/fund-management#list-payment-methods)</td>
         <td>`/v1/payments/methods`</td>
         <td>`banks:read, banks:create`</td>
      </tr>
      <tr>
         <td>[New Clearing Order](/rest/clearing#create-new-clearing-order)</td>
         <td>`/v1/clearing/new`</td>
         <td>`clearing:create`</td>
      </tr>
      <tr>
         <td>[Cancel Clearing Order](/rest/clearing#cancel-clearing-order)</td>
         <td>`/v1/clearing/cancel`</td>
         <td>`clearing:create`</td>
      </tr>
      <tr>
         <td>[Confirm Clearing Order](/rest/clearing#confirm-clearing-order)</td>
         <td>`/v1/clearing/confirm`</td>
         <td>`clearing:create`</td>
      </tr>
      <tr>
         <td>[Clearing Order Status](/rest/clearing#get-clearing-order)</td>
         <td>`/v1/clearing/status`</td>
         <td>`clearing:read`</td>
      </tr>
      <tr>
         <td>[Clearing Order List](/rest/clearing#list-clearing-orders)</td>
         <td>`/v1/clearing/list`</td>
         <td>`clearing:read`</td>
      </tr>
      <tr>
         <td>[Clearing Broker List](/rest/clearing#list-clearing-brokers)</td>
         <td>`/v1/clearing/broker/list`</td>
         <td>`clearing:read`</td>
      </tr>
      <tr>
         <td>[Clearing Trades](/rest/clearing#list-clearing-trades)</td>
         <td>`/v1/clearing/trades`</td>
         <td>`clearing:read`</td>
      </tr>
      <tr>
         <td>[Withdraw Crypto Funds](/rest/fund-management#withdraw-crypto-funds)</td>
         <td>`/v1/withdraw/:currency`</td>
         <td>`crypto:send`</td>
      </tr>
      <tr>
         <td>[List Past Trades](/rest/orders#list-past-trades)</td>
         <td>`/v1/mytrades`</td>
         <td>`history:read`</td>
      </tr>
      <tr>
         <td>[Get Orders History](/rest/orders#list-past-orders)</td>
         <td>`/v1/orders/history`</td>
         <td>`history:read`</td>
      </tr>
      <tr>
         <td>[Get Notional Volume](/rest/orders#get-notional-trading-volume)</td>
         <td>`/v1/notionalvolume`</td>
         <td>`history:read`</td>
      </tr>
      <tr>
         <td>[Get Trade Volume](/rest/orders#get-trading-volume)</td>
         <td>`/v1/tradevolume`</td>
         <td>`history:read`</td>
      </tr>
      <tr>
         <td>[Transfers](/rest/fund-management#list-past-transfers)</td>
         <td>`/v1/transfers`</td>
         <td>`history:read`</td>
      </tr>
      <tr>
         <td>[Custody Account Fees](/rest/fund-management#list-custody-fee-transfers)</td>
         <td>`/v1/custodyaccountfees`</td>
         <td>`history:read`</td>
      </tr>
      <tr>
         <td>[Create New Order](/rest/orders#create-new-order)</td>
         <td>`/v1/order/new`</td>
         <td>`orders:create`</td>
      </tr>
      <tr>
         <td>[Cancel Order](/rest/orders#cancel-order)</td>
         <td>`/v1/order/cancel`</td>
         <td>`orders:create`</td>
      </tr>
      <tr>
         <td>[Cancel All Session Orders](/rest/orders#cancel-all-session-orders)</td>
         <td>`/v1/order/cancel/session`</td>
         <td>`orders:create`</td>
      </tr>
      <tr>
         <td>[Cancel All Active Orders](/rest/orders#cancel-all-active-orders)</td>
         <td>`/v1/order/cancel/all`</td>
         <td>`orders:create`</td>
      </tr>
      <tr>
         <td>[Wrap Order](/rest/orders#wrap-order)</td>
         <td>`/v1/wrap/:symbol`</td>
         <td>`orders:create`</td>
      </tr>
      <tr>
         <td>[Get Instant Quote](/rest/instant#get-instant-quote)</td>
         <td>`/v1/instant/quote`</td>
         <td>`orders:create`</td>
      </tr>
      <tr>
         <td>[Execute Instant Order](/rest/instant#execute-instant-order)</td>
         <td>`/v1/instant/execute`</td>
         <td>`orders:create`</td>
      </tr>
      <tr>
         <td>[Get Order Status](/rest/orders#get-order-status)</td>
         <td>`/v1/order/status`</td>
         <td>`orders:read`</td>
      </tr>
      <tr>
         <td>[Get Active Orders](/rest/orders#list-active-orders)</td>
         <td>`/v1/orders`</td>
         <td>`orders:read`</td>
      </tr>
      <tr>
         <td>[Account Detail](/rest/account-administration#get-account-detail)</td>
         <td>`/v1/account`</td>
         <td>`account:read`</td>
      </tr>
      <tr>
         <td>[Get Terms Status](/rest-api/prediction-markets/terms/get-terms-status)</td>
         <td>`/v1/prediction-markets/terms/status`</td>
         <td>`orders:read`</td>
      </tr>
      <tr>
         <td>[Accept Terms](/rest-api/prediction-markets/terms/accept-terms)</td>
         <td>`/v1/prediction-markets/terms/accept`</td>
         <td>`orders:create`</td>
      </tr>
      <tr>
         <td>[Place Prediction Market Order](/rest-api/prediction-markets/order-management/place-order)</td>
         <td>`/v1/prediction-markets/order`</td>
         <td>`orders:create`</td>
      </tr>
      <tr>
         <td>[Cancel Prediction Market Order](/rest-api/prediction-markets/order-management/cancel-order)</td>
         <td>`/v1/prediction-markets/order/cancel`</td>
         <td>`orders:create`</td>
      </tr>
      <tr>
         <td>[Get Active Prediction Market Orders](/rest-api/prediction-markets/order-management/get-active-orders)</td>
         <td>`/v1/prediction-markets/orders/active`</td>
         <td>`orders:read`</td>
      </tr>
      <tr>
         <td>[Get Prediction Market Order History](/rest-api/prediction-markets/order-management/get-order-history)</td>
         <td>`/v1/prediction-markets/orders/history`</td>
         <td>`orders:read`</td>
      </tr>
      <tr>
         <td>[Get Prediction Market Positions](/rest-api/prediction-markets/positions/get-positions)</td>
         <td>`/v1/prediction-markets/positions`</td>
         <td>`orders:read`</td>
      </tr>
      <tr>
         <td>[Get Settled Prediction Market Positions](/rest-api/prediction-markets/positions/get-settled-positions)</td>
         <td>`/v1/prediction-markets/positions/settled`</td>
         <td>`orders:read`</td>
      </tr>
      <tr>
         <td>[Get Prediction Market Volume Metrics](/rest-api/prediction-markets/positions/get-volume-metrics)</td>
         <td>`/v1/prediction-markets/metrics/volume`</td>
         <td>`orders:read`</td>
      </tr>
      <tr>
         <td>[List Maker Rebate Payouts](/rest-api/prediction-markets/rewards/list-maker-rebate-payouts)</td>
         <td>`/v1/prediction-markets/maker-rebate/payouts`</td>
         <td>`orders:read`</td>
      </tr>
      <tr>
         <td>[Get Maker Rebate Lifetime Summary](/rest-api/prediction-markets/rewards/get-maker-rebate-lifetime-summary)</td>
         <td>`/v1/prediction-markets/maker-rebate/summary/total`</td>
         <td>`orders:read`</td>
      </tr>
      <tr>
         <td>[Get Liquidity Rewards Daily Summary](/rest-api/prediction-markets/rewards/get-liquidity-rewards-daily-summary)</td>
         <td>`/v1/prediction-markets/liquidity-rewards/summary/daily`</td>
         <td>`orders:read`</td>
      </tr>
      <tr>
         <td>[Get Liquidity Rewards Lifetime Summary](/rest-api/prediction-markets/rewards/get-liquidity-rewards-lifetime-summary)</td>
         <td>`/v1/prediction-markets/liquidity-rewards/summary/total`</td>
         <td>`orders:read`</td>
      </tr>
   </tbody>
</table>


API keys use different roles for to access Gemini APIs. Please see [roles](/roles) for descriptions of each role and scope for API keys.

## Revoke OAuth Token

See [Revoke OAuth Token Endpoint](/rest/o-auth#revoke-o-auth-token)

## Revision History
| Date       | Notes                       |
|------------|-----------------------------|
| 2020/08/20 | Initial OAuth documentation |
