Coinbase Developer Platform (CDP) uses server and client API keys to authenticate access.

  • Secret API Keys: For server-to-server communication (i.e., REST APIs).
  • Client API Keys: For client-side communication (i.e., JSON-RPC).

For more information, see CDP API Keys.

Prerequisites

It is assumed you are logged into an existing CDP account (if not, create one).

1. Create an API key

Your CDP account should include a project by default.

Navigate to your API keys dashboard. From the top drop-down, select your desired project.

Continue reading based on the type of API key you need to create.

Server

To create a Secret API key (for server-to-server communication), ensure the Secret API Keys tab is selected as shown in the previous step.

Click the Create API key button and give your key a name.

You also have the option to:

  • Set an IP allowlist for the key
  • Restrict granular permissions such as the ability to trade or transfer funds
  • Select between Ed25519 (Recommended) or ECDSA signature algorithms

When you are satisfied with your key configuration, click Create & download:

A modal will appear with your key details.

Make sure you save the API key ID and Secret in a safe place. You can’t re-download it later.

To regenerate a Secret API key, click Configure to delete and recreate the key.

Now, you are ready to use our REST and server-side APIs!

Client

To create a Client API key (for use in front-end components) ensure the Client API Key tab is selected.

Copy the Client API key and export it as an environment variable:

export CLIENT_API_KEY="your_client_api_key"

Click the Rotate button to expire this key and generate a new one.

Proceed to Step 3.

2. Generate JWT (Server only)

You can generate a JSON Web Token (JWT) using the following code snippets.

Continue reading to:

  • Set up your environment for JWT generation by configuring environment variables and installing dependencies
  • Export your generated JWT as an environment variable

Never include Secret API key information in your code.

Instead, securely store it and retrieve it from an environment variable, a secure database, or other storage mechanism intended for highly-sensitive parameters.

Setup

To begin, export the following environment variables:

  • KEY_NAME: The name of the API key you want to use
  • KEY_SECRET: The secret of the API key you want to use
  • REQUEST_METHOD: The HTTP method of the endpoint you want to target
  • REQUEST_PATH: The path of the endpoint you want to target
  • REQUEST_HOST: The host of the endpoint you want to target

For example:

export KEY_NAME="organizations/{org_id}/apiKeys/{key_id}"
export KEY_SECRET="-----BEGIN EC PRIVATE KEY-----\nYOUR PRIVATE KEY\n-----END EC PRIVATE KEY-----\n"
export REQUEST_METHOD="GET"
export REQUEST_PATH="/api/v3/brokerage/accounts"
export REQUEST_HOST="api.coinbase.com"

Newlines must be preserved to properly parse the key secret. Do this on one line by using \n to escape new lines, or via a multi-line string.

Complete the remaining setup steps for JWT generation below according to your language choice.

Install required dependencies:

pip install PyJWT==2.8.0
pip install cryptography==42.0.5

Export

Now that your environment is setup, you can create the code to generate the JWT and export it as an environment variable.

Your JWT is valid for 2 minutes. After 2 minutes, you will need to generate a new JWT to ensure uninterrupted access to the CDP APIs.

Create a new file for JWT generation code:

touch main.py

It should contain the following:

main.py
import jwt
from cryptography.hazmat.primitives import serialization
import time
import secrets
import os 

# Fetch values from exported environment variables
key_name = os.getenv('KEY_NAME')  
key_secret = os.getenv('KEY_SECRET') 
request_method = os.getenv('REQUEST_METHOD')  
request_host = os.getenv('REQUEST_HOST')  
request_path = os.getenv('REQUEST_PATH')  

def build_jwt(uri):
    private_key_bytes = key_secret.encode('utf-8')
    private_key = serialization.load_pem_private_key(private_key_bytes, password=None)
    jwt_payload = {
        'sub': key_name,
        'iss': "cdp",
        'nbf': int(time.time()),
        'exp': int(time.time()) + 120,
        'uri': uri,
    }
    jwt_token = jwt.encode(
        jwt_payload,
        private_key,
        algorithm='ES256',
        headers={'kid': key_name, 'nonce': secrets.token_hex()},
    )
    return jwt_token
def main():
    uri = f"{request_method} {request_host}{request_path}"
    jwt_token = build_jwt(uri)
    print(jwt_token)
if __name__ == "__main__":
    main()

Finally, run the script to generate the JWT output and export it as an environment variable.

export JWT=$(python main.py)
echo $JWT

3. Authenticate

Server

To authenticate your server-side code, use the JWT token you generated in the previous step as a Bearer Token within your request:

export API_ENDPOINT="https://$REQUEST_HOST$REQUEST_PATH"

# Now, use that endpoint in your curl command
curl -L -X "$HTTP_METHOD" "$API_ENDPOINT" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json"

As an example, Get Asset by ID could be requested like so:

curl -L -X POST "https://api.cdp.coinbase.com/platform/v1/networks/base-mainnet/assets/BTC" \
  -H "Authorization: Bearer ${JWT}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json"

Client

To authenticate your client-side code, include it with your JSON-RPC request:

curl -L -X https://api.developer.coinbase.com/rpc/v1/base/${CLIENT_API_KEY} \
  -H "Content-Type: application/json" \
  -d '${REQUEST_BODY_JSON}'

As an example, you can request the List Historical Balances JSON-RPC endpoint like so:

curl -L -X https://api.developer.coinbase.com/rpc/v1/base/${CLIENT_API_KEY} \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc": "2.0", "id": 1, "method": "cdp_listBalances", "params": [{"address":"0xF7DCa789B08Ed2F7995D9bC22c500A8CA715D0A8","pageToken":"","pageSize":1}]}'