-
-
Save marianzange/354edb2f74e88491f6fa520ea8beb2d8 to your computer and use it in GitHub Desktop.
// Computes the HMAC for requests sent to the Coinbase Pro API. | |
// | |
// - Add the following code as Postman pre-request script | |
// - Adapt the getPatch function an the variable names according to your needs | |
const timestamp = Date.now() / 1000; | |
function getPath(url) { | |
// URL path regex works only if your URLs look like this: {{api_url}}/resource | |
// If you use hardcoded URLs or any other scheme, adapt the regex pattern! | |
const matches = url.match(/.+?(\/.+?)(?:#|\?|$)/); | |
return (matches && matches.length > 1) ? matches[1] : ''; | |
} | |
function computeSignature(request) { | |
const data = request.data; | |
const method = request.method; | |
const path = getPath(request.url); | |
const body = (method === 'GET' || !data) ? '' : JSON.stringify(data); | |
const message = timestamp + method + path + body; | |
const key = CryptoJS.enc.Base64.parse(pm.variables.get('CB-SECRET')); | |
const hash = CryptoJS.HmacSHA256(message, key).toString(CryptoJS.enc.Base64); | |
return hash; | |
} | |
postman.setEnvironmentVariable('hmacSignature', computeSignature(request)); | |
postman.setEnvironmentVariable('hmacTimestamp', timestamp) |
I tried the following but doesn't seem to work. Just get an Invalid API Key response. Although, I have double checked my key, passphrase, and secret. Any thoughts?
{
"message": "Invalid API Key"
}
// Computes the HMAC for requests sent to the Coinbase Pro API.
//
// - Add the following code as Postman pre-request script
// - Adapt the getPatch function an the variable names according to your needs
const timestamp = Math.ceil(Date.now() / 1000);
const secret = pm.variables.get('CB-SECRET');
function getPath(url) {
// URL path regex works only if your URLs look like this: {{api_url}}/resource
// If you use hardcoded URLs or any other scheme, adapt the regex pattern!
const matches = url.match(/.+?(\/.+?)(?:#|\?|$)/);
return (matches && matches.length > 1) ? matches[1] : '';
}
function computeSignature(request) {
const data = request.data;
const method = request.method;
const path = getPath(request.url);
const body = (method === 'GET' || !data) ? '' : JSON.stringify(data);
const message = timestamp + method + path + body;
const key = CryptoJS.enc.Base64.parse(secret);
const hash = CryptoJS.HmacSHA256(message, key).toString(CryptoJS.enc.Base64);
return hash;
}
var sign = computeSignature(request);
// Not sure if this still needs to be here?
postman.setEnvironmentVariable('hmacSignature', sign);
postman.setEnvironmentVariable('hmacTimestamp', timestamp);
pm.request.headers.upsert({ key: 'CB-ACCESS-KEY', value: pm.variables.get('CB-ACCESS-KEY')});
pm.request.headers.upsert({ key: 'CB-ACCESS-SIGN', value: sign });
pm.request.headers.upsert({ key: 'CB-ACCESS-TIMESTAMP', value: timestamp });
pm.request.headers.upsert({ key: 'CB-ACCESS-PASSPHRASE', value: pm.variables.get('CB-ACCESS-PASSPHRASE') });
Hi @jakeashcraft,
The code example below is fully working, I tested myself couple of hours ago, just replace the api-key, passphrase and secret accordingly.
// Computes the HMAC for requests sent to the Coinbase Pro API.
//
// - Add the following code as Postman pre-request script
// - Adapt the getPatch function an the variable names according to your needs
const timestamp = Math.ceil(Date.now() / 1000);
pm.environment.set("CB-SECRET", "secret");
function getPath(url) {
// URL path regex works only if your URLs look like this: {{api_url}}/resource
// If you use hardcoded URLs or any other scheme, adapt the regex pattern!
const matches = url.match(/.+?(\/.+?)(?:#|\?|$)/);
return (matches && matches.length > 1) ? matches[1] : '';
}
function computeSignature(request) {
const data = request.data;
const method = request.method;
const path = getPath(request.url);
const body = (method === 'GET' || !data) ? '' : JSON.stringify(data);
const message = timestamp + method + path + body;
const key = CryptoJS.enc.Base64.parse(pm.variables.get('CB-SECRET'));
const hash = CryptoJS.HmacSHA256(message, key).toString(CryptoJS.enc.Base64);
return hash;
}
pm.environment.set("CB-ACCESS-KEY", "api-key");
pm.environment.set('CB-ACCESS-PASSPHRASE', "passphrase")
pm.environment.set('CB-ACCESS-SIGN', computeSignature(request));
pm.environment.set('CB-ACCESS-TIMESTAMP', timestamp)
// Add or update an existing header
pm.request.headers.upsert({
key: 'CB-ACCESS-KEY',
value: 'api-key'
});
pm.request.headers.upsert({
key: 'CB-ACCESS-PASSPHRASE',
value: 'passphrase'
});
pm.request.headers.upsert({
key: 'CB-ACCESS-SIGN',
value: computeSignature(request)
});
pm.request.headers.upsert({
key: 'CB-ACCESS-TIMESTAMP',
value: timestamp
});
Hi @lasoares can u show environment and collection?(hide secret key ofc) Can use this for non pro api?
Hi @lasoares can u show environment and collection?(hide secret key ofc) Can use this for non pro api?
Yes, you can use also for sandbox environment: https://api-public.sandbox.pro.coinbase.com
Below is my environment collection.
item": [
{
"name": "Get an Order",
"event": [
{
"listen": "prerequest",
"script": {
"exec": [
"\r",
"// Computes the HMAC for requests sent to the Coinbase Pro API.\r",
"//\r",
"// - Add the following code as Postman pre-request script\r",
"// - Adapt the getPatch function an the variable names according to your needs\r",
"\r",
"const timestamp = Math.ceil(Date.now() / 1000);\r",
"\r",
"pm.environment.set(\"CB-SECRET\", \"hide\");\r",
"\r",
"function getPath(url) {\r",
" // URL path regex works only if your URLs look like this: {{api_url}}/resource\r",
" // If you use hardcoded URLs or any other scheme, adapt the regex pattern!\r",
" const matches = url.match(/.+?(\\/.+?)(?:#|\\?|$)/);\r",
" return (matches && matches.length > 1) ? matches[1] : ''; \r",
"}\r",
" \r",
"function computeSignature(request) {\r",
" const data = request.data;\r",
" const method = request.method;\r",
" const path = getPath(request.url);\r",
" const body = (method === 'GET' || !data) ? '' : JSON.stringify(data);\r",
" const message = timestamp + method + path + body;\r",
" const key = CryptoJS.enc.Base64.parse(pm.variables.get('CB-SECRET'));\r",
" const hash = CryptoJS.HmacSHA256(message, key).toString(CryptoJS.enc.Base64);\r",
"\r",
" return hash;\r",
"}\r",
"\r",
"pm.environment.set(\"CB-ACCESS-KEY\", \"hide\"); \r",
"pm.environment.set('CB-ACCESS-PASSPHRASE', \"hide\")\r",
"pm.environment.set('CB-ACCESS-SIGN', computeSignature(request));\r",
"pm.environment.set('CB-ACCESS-TIMESTAMP', timestamp)\r",
"\r",
"// Add or update an existing header\r",
"pm.request.headers.upsert({\r",
" key: 'CB-ACCESS-KEY',\r",
" value: 'hide'\r",
"});\r",
"\r",
"pm.request.headers.upsert({\r",
" key: 'CB-ACCESS-PASSPHRASE',\r",
" value: 'hide'\r",
"});\r",
"\r",
"pm.request.headers.upsert({\r",
" key: 'CB-ACCESS-SIGN',\r",
" value: computeSignature(request)\r",
"});\r",
"\r",
"pm.request.headers.upsert({\r",
" key: 'CB-ACCESS-TIMESTAMP',\r",
" value: timestamp\r",
"});"
],
"type": "text/javascript"
}
}
],
"request": {
"method": "GET",
"header": [
{
"key": "Content-Type",
"value": "application/json",
"type": "text"
}
],
"url": {
"raw": "{{api_url_sandbox}}/accounts",
"host": [
"{{api_url_sandbox}}"
],
"path": [
"accounts"
]
}
},
"response": []
}]
"variable": [
{
"key": "api_url",
"value": "https://api.pro.coinbase.com"
},
{
"key": "api_url_sandbox",
"value": "https://api-public.sandbox.pro.coinbase.com"
}
]
Why are you setting CB-ACCESS-PASSPHRASE? I can't see that this is mentioned in their API documentation?
Interesting. I was reading the non-Pro documentation of Coinbase API. Thanks for informing me!
@amgreen2 Try setting the API endpoint as a Postman variable such as {{api_url}}
or adapt the regex to your needs. The regex in the code snippet is a bit crappy.
I am also getting same issue that what amgreen2 is facing.
"Invalid signature"
I was having the same "Invalid API Key" error, but I had overlooked a couple things while struggling to fix the problem. Everything is now working, and here were the troubleshooting steps that I did:
- Add a collection variable: click on the "..." next to your collection in the left sidebar --> variables. Add api_url as variable and "https://api.pro.coinbase.com" as initial value.
- Change your request URL to be: {{api_url}}/accounts (or whatever API endpoint you're targeting).
- Make sure your CB-ACCESS-KEY is copied into both the "pm.environment" and "pm.request.headers.upsert" lines. I had overlooked updating pm.request.headers.upsert.
- Make sure your CB-ACCESS-PASSPHRASE is copied into both the "pm.environment" and "pm.request.headers.upsert" lines.
Everything should work fine after this. Thanks to everyone in this thread for your help!
Here's how I got it working for the non-pro API.
CB-SECRET
is set as an environment variable, the rest I've just put directly in my request.
- Uses
Math.floor
instead ofceil
simply because that's the example given by Coinbase - Passes the HMAC the secret as a string rather than base64 parsing it
- Wants a hex digest rather than base64
- No need for regex for the path, postman provides an array:
pm.request.url.path
(needs joining with/
)
const timestamp = Math.floor(Date.now() / 1000);
console.log(timestamp);
function computeSignature(request) {
const data = request.data;
const method = request.method;
const path = "/" + pm.request.url.path.join("/");
const body = (method === 'GET' || !data) ? '' : JSON.stringify(data);
const message = timestamp + method + path + body;
const key = pm.variables.get('CB-SECRET');
const hash = CryptoJS.HmacSHA256(message, key).toString(CryptoJS.enc.Hex);
console.log("Message: " + message + " HMAC: " + hash);
return hash;
}
pm.environment.set('CB-ACCESS-SIGN', computeSignature(request));
pm.environment.set('CB-ACCESS-TIMESTAMP', timestamp);
This works for me. I had to change this line:
const body = (method === 'GET' || !data) ? '' : JSON.stringify(data);
to
const body = (method === 'GET' || !data) ? '' : data;
Script:
const timestamp = Date.now() / 1000;
pm.environment.set("CB-SECRET", "your-secret");
function computeSignature(request) {
const data = request.data;
const method = request.method;
const path = "/" + pm.request.url.path.join("/");
const body = (method === 'GET' || !data) ? '' : data;
const message = timestamp + method + path + body;
const key = CryptoJS.enc.Base64.parse(pm.variables.get('CB-SECRET'));
const hash = CryptoJS.HmacSHA256(message, key).toString(CryptoJS.enc.Base64);
return hash;
}
pm.environment.set('CB-ACCESS-SIGN', computeSignature(request));
pm.environment.set('CB-ACCESS-TIMESTAMP', timestamp);
@lasoares do you have a complete example showing your changes?