调用Coinbase Candles API遇参数错误:请求蜡烛数需小于300
Coinbase Candles API 参数错误排查:蜡烛数超过300限制
问题描述
调用Coinbase Candles接口时返回如下错误:
{"error":"INVALID_ARGUMENT","error_details":"start and end argument is invalid - number of candles requested should be less than 300 ","message":"start and end argument is invalid - number of candles requested should be less than 300 "}
用户调用代码如下:
using RestSharp; using System.Globalization; using System.Net.Http; using System.Security.Cryptography; using System.Text; var symbol = "BTC-GBP"; var _privateApiKey = "xxxx"; var _secret = "xxxxxxxxxx"; var _timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(); var _requestPath = "/api/v3/brokerage/products/" + symbol + "/candles"; var _method = "GET"; var client = new RestClient(@"https://api.coinbase.com" + _requestPath + "?granularity=ONE_DAY&start=" + DateTime.Now.AddMilliseconds(-3000).ToUniversalTime().Ticks + "&end=" + DateTime.Now.ToUniversalTime().Ticks + ""); var request = new RestRequest(); request.Method = Method.Get; request.AddHeader("Content-Type", "application/json"); request.AddHeader("CB-ACCESS-KEY", _privateApiKey); request.AddHeader("CB-ACCESS-TIMESTAMP", _timestamp); request.AddHeader("CB-ACCESS-SIGN", GetAccessSign(_timestamp, _method, _requestPath, "", _secret)); request.AddHeader("CB-VERSION", "2023-01-18"); try { var response = client.Execute(request); Console.WriteLine(response.Content); } catch (Exception e) { Console.WriteLine(e.Message); } Console.ReadLine(); string GetAccessSign(string timestamp, string method, string path, string body, string apiSecret) { var convertedString = Convert.FromBase64String(apiSecret); var hmaccsha = new HMACSHA256(convertedString); string timestampStr = timestamp; string httpMethodStr = method; var prehash = timestampStr + httpMethodStr + path + body; // Convert the input string and key to byte arrays byte[] prehashBytes = Encoding.UTF8.GetBytes(prehash); byte[] keyBytes = Encoding.UTF8.GetBytes(apiSecret); // Compute the SHA-256 hash of the input data using the key HMACSHA256 hmac = new HMACSHA256(keyBytes); byte[] hash2 = hmac.ComputeHash(prehashBytes); // Convert the hash to a hexadecimal string string signedSignature = BitConverter.ToString(hash2).Replace("-", "").ToLower(); return signedSignature; }
错误原因分析
- 时间参数格式不匹配:
Coinbase API要求start和end参数为Unix时间戳(秒或毫秒),但代码中使用了.Ticks(.NET中表示从0001年1月1日开始的100纳秒数),这个值会被API解析为极其久远的时间,导致计算出的蜡烛数量远超300的限制。 - 签名生成逻辑错误:
签名函数中先将apiSecret通过Base64解码,后续又用UTF8编码apiSecret作为HMAC密钥,这会导致签名无效(正确做法是使用Base64解码后的字节作为密钥)。
修复方案
1. 修正时间参数格式
使用Unix时间戳(秒级,与CB-ACCESS-TIMESTAMP保持一致)替代.Ticks,同时确保时间范围对应的蜡烛数不超过300:
// 获取UTC时间的秒级Unix时间戳 var now = DateTimeOffset.UtcNow; var endTimestamp = now.ToUnixTimeSeconds(); // 示例:取最近200天的日K(ONE_DAY粒度下,200<300,符合限制) var startTimestamp = now.AddDays(-200).ToUnixTimeSeconds(); // 改用RestSharp的AddParameter添加查询参数,避免手动拼接的编码问题 var client = new RestClient("https://api.coinbase.com"); var request = new RestRequest(_requestPath, Method.Get); request.AddParameter("granularity", "ONE_DAY"); request.AddParameter("start", startTimestamp); request.AddParameter("end", endTimestamp);
2. 修正签名生成函数
使用Base64解码后的apiSecret作为HMAC密钥,确保签名正确:
string GetAccessSign(string timestamp, string method, string path, string body, string apiSecret) { // 正确使用Base64解码apiSecret作为HMAC密钥 var keyBytes = Convert.FromBase64String(apiSecret); var prehash = $"{timestamp}{method}{path}{body}"; var prehashBytes = Encoding.UTF8.GetBytes(prehash); using var hmac = new HMACSHA256(keyBytes); var hashBytes = hmac.ComputeHash(prehashBytes); return BitConverter.ToString(hashBytes).Replace("-", "").ToLower(); }
注意事项
- 不同粒度对应的最大时间范围:比如
ONE_DAY粒度最多请求299天(300个蜡烛),ONE_HOUR最多请求299小时,以此类推。 - 始终使用UTC时间避免时区偏差,推荐用
DateTimeOffset处理时间。 - 避免手动拼接URL参数,使用RestSharp的
AddParameter方法自动处理编码。
内容的提问来源于stack exchange,提问作者redoc01
相关产品推荐
相关产品推荐

