Prime REST API Requests
To start using the Prime REST API, open a Coinbase Prime account, create an API key, and authenticate.
The REST API has endpoints for account and order management as well as public market data.
https://api.prime.coinbase.com
Requests and responses have an application/json
Content-Type
and follow standard HTTP response status codes for success and failures.
Creating a Request
Request bodies should have content type application/json
and be valid JSON. For instructions on creating a valid X-CB-ACCESS-SIGNATURE
, see API Authentication.
curl --request GET \
--url 'https://api.prime.coinbase.com/v1/<API_PATH>' \
--header 'X-CB-ACCESS-KEY: <ACCESS_KEY>' \
--header 'X-CB-ACCESS-PASSPHRASE: <PASSPHRASE>' \
--header 'X-CB-ACCESS-SIGNATURE: <SIGNATURE>' \
--header 'X-CB-ACCESS-TIMESTAMP: <TIMESTAMP>' \
--header 'Content-Type: application/json'
Retrieving IDs
Many API requests require either a portfolio_id
or an entity_id
value:
- Your
portfolio_id
can be retrieved by calling GET Portfolios. - Your
entity_id
can be retrieved by calling GET Portfolio Users with yourportfolio_id
.
Sample Requests
The following Python and JavaScript snippets demonstrate an end-to-end Prime API request.
Python
import json, hmac, hashlib, time, requests, base64
from requests.auth import AuthBase
class CoinbasePrimeAuth(AuthBase):
def __init__(self, key, secret, passphrase):
self.api_key = key
self.secret_key = secret
self.passphrase = passphrase
def __call__(self, request):
timestamp = str(int(time.time()))
message = timestamp + request.method + request.path_url.split('?')[0] + str(request.body or '')
signature = hmac.new(self.secret_key.encode('utf-8'), message.encode('utf-8'), digestmod=hashlib.sha256).digest()
signature_b64 = base64.b64encode(signature).decode()
request.headers.update({
'X-CB-ACCESS-SIGNATURE': signature_b64,
'X-CB-ACCESS-TIMESTAMP': timestamp,
'X-CB-ACCESS-KEY': self.api_key,
'X-CB-ACCESS-PASSPHRASE': self.passphrase,
'Accept': 'application/json'
})
return request
def get_an_order():
api_url = 'https://api.prime.coinbase.com'
api_key = "YOUR_API_KEY_HERE"
api_secret = "YOUR_API_SECRET_HERE"
passphrase = "YOUR_PASSPHRASE_HERE"
auth = CoinbasePrimeAuth(api_key, api_secret, passphrase)
portfolio_id = "YOUR_PORTFOLIO_ID_HERE"
order_id = "YOUR_ORDER_ID_HERE"
# Get accounts
resp = requests.get(api_url + f'/v1/portfolios/{portfolio_id}/orders/{order_id}', auth=auth)
resp_json = json.loads(resp.text)
print(resp_json)
if __name__ == "__main__":
get_an_order()
JavaScript
// native NodeJS https module
const https = require('https');
// Google's crypto-js packae via https://www.npmjs.com/package/crypto-js
const CryptoJS = require('crypto-js');
// Derived from your Coinbase Prime API Key
// SIGNING_KEY: the signing key provided as a part of your API key
// ACCESS_KEY: the access key provided as a part of your API key
// PASSPHRASE: the PASSPHRASE key provided as a part of your API key
const SIGNING_KEY = process.env.SIGNING_KEY;
const ACCESS_KEY = process.env.ACCESS_KEY;
const PASSPHRASE = process.env.PASSPHRASE;
const REST_METHODS = {
GET: 'GET',
POST: 'POST',
PUT: 'PUT',
DELETE: 'DELETE',
};
// Your unique entity ID
const ENTITY_ID = process.env.ENTITY_ID;
// A specific portfolio ID (only necessary if relevant to the request you're making)
const PORTFOLIO_ID = process.env.PORTFOLIO_ID;
// The base URL of the API
const PROD_URL = 'api.prime.coinbase.com';
// The path of the API endpoint being called
let requestPath = `/v1/portfolios/${PORTFOLIO_ID}`;
// The method of the request: GET, POST, PUT, DELETE, etc
let method = REST_METHODS.GET;
// Request signatures require a current UNIX timestamp in seconds that is
// embedded in the signed payload to verify against server clock.
const currentTimeInSecs = Math.floor(Date.now() / 1000);
// Body will be JSON (POST) or empty string (GET)
const body = '';
// Function to generate a signature using CryptoJS
function sign(str, secret) {
const hash = CryptoJS.HmacSHA256(str, secret);
return hash.toString(CryptoJS.enc.Base64);
}
// Function to build the payload required to sign
function buildPayload(ts, method, requestPath, body) {
return `${ts}${method}${requestPath}${body}`;
}
// Build the string we want to sign using information defined above
const strToSign = buildPayload(currentTimeInSecs, method, requestPath, body);
// Sign it!
const sig = sign(strToSign, SIGNING_KEY);
// Use Postman's scripting objects to append the header values
const headers = new Map();
headers.set('X-CB-ACCESS-KEY', ACCESS_KEY);
headers.set('X-CB-ACCESS-PASSPHRASE', PASSPHRASE);
headers.set('X-CB-ACCESS-SIGNATURE', sig);
headers.set('X-CB-ACCESS-TIMESTAMP', currentTimeInSecs);
headers.set('Content-Type', 'application/json');
const requestOptions = {
hostname: PROD_URL,
path: requestPath,
method: REST_METHODS.GET,
headers: Object.fromEntries(headers),
};
https.get(requestOptions, res => {
let data = [];
console.log('Status Code:', res.statusCode);
res.on('data', chunk => {
data.push(chunk);
});
res.on('end', () => {
console.log('Response ended: ');
const parsedResponse = JSON.parse(Buffer.concat(data).toString());
console.log(parsedResponse);
});
}).on('error', err => {
console.log('Error: ', err.message);
});
Errors
Unless otherwise stated, bad requests respond with HTTP 4xx
or 5xx
status codes. The body also contains a message
parameter indicating the cause.
Your implementation language's HTTP library should be configured to provide message bodies for non-2xx
requests so that you can read the message field from the body.
Common error codes
Error Code | Meaning | Description |
---|---|---|
400 | Bad Request | Invalid request format |
401 | Unauthorized | Invalid API Key |
403 | Forbidden | You do not have access to the requested resource |
404 | Not Found | Requested resource could not be found |
500 | Internal Server Error | Server-side error occurred |
Success
A successful response is indicated by HTTP status code 200
and may contain an optional body. If the response has a body, it will be documented under the related endpoint resource below.