You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Coinbase API问题:链下转账请求出现401 invalid signature错误

Troubleshooting Coinbase API Off-Chain Transfer 401 "Invalid Signature" Error

我之前也踩过Coinbase API签名验证的坑,401 "invalid signature"确实让人头大——尤其是明明跟着文档步骤走还是出问题的时候。针对你用邮箱地址做链下转账的场景,咱们一步步排查可能的问题:

1. 签名核心参数是否完全匹配Coinbase要求

Coinbase的签名验证对细节要求极高,差一点都不行,重点检查这几个点:

  • 时间戳一致性:请求头里的CB-ACCESS-TIMESTAMP必须是Unix秒级时间戳,且和签名生成时用的时间戳完全一致。另外,这个时间戳和Coinbase服务器时间差不能超过30秒,要是本地时间不准,建议先调用GET /v2/time接口同步时间。
  • 请求路径准确性:签名里的路径要和实际请求的路径完全一致,比如不能把/v2/accounts/{account_id}/transactions写成/accounts/{account_id}/transactions(漏了版本号),也不能多/少斜杠。
  • 请求体哈希正确性:POST请求的签名需要包含请求体的SHA256哈希值(转十六进制字符串)。注意要用原始未格式化的JSON字符串计算哈希——比如不能用带换行、缩进的美化版JSON,必须是压缩后的纯字符串。

2. 转账请求体格式是否合规

用邮箱做链下转账的请求体必须严格符合Coinbase规范,示例如下(别自己瞎改字段名):

{
  "type": "send",
  "to": "target-user@example.com",
  "amount": "5.0",
  "currency": "BTC"
}

检查点:

  • 所有键名必须用双引号,不能有多余逗号
  • type必须是send,to字段要准确填写目标邮箱
  • amount是字符串格式(避免浮点精度问题),currency要和转出账户的币种一致

3. API密钥权限是否足够

Coinbase API密钥默认没有转账权限!你需要在创建密钥时手动勾选wallet:transactions:send权限。别小看这个,有时候权限不足也会被包装成"invalid signature"错误返回。

4. 签名算法实现是否正确

Coinbase要求用HMAC-SHA256算法生成签名,核心逻辑是:

  1. 拼接字符串:时间戳 + HTTP方法 + 请求路径 + 请求体哈希
  2. 用API密钥的CB-ACCESS-SECRET作为密钥,对拼接后的字符串做HMAC-SHA256加密
  3. 把加密结果转成十六进制字符串,作为CB-ACCESS-SIGN请求头的值

给你一个Python的标准实现参考(对比下你的代码是否有差异):

import hmac
import hashlib
import time
import requests

api_key = "你的API_KEY"
api_secret = "你的API_SECRET"
account_id = "转出账户ID"
url = f"https://api.coinbase.com/v2/accounts/{account_id}/transactions"

# 生成时间戳
timestamp = str(int(time.time()))
# 构造请求体(压缩后的JSON)
request_body = '{"type":"send","to":"target-user@example.com","amount":"5.0","currency":"BTC"}'
# 拼接签名用的消息
message = timestamp + 'POST' + f'/v2/accounts/{account_id}/transactions' + request_body
# 生成签名
signature = hmac.new(api_secret.encode('utf-8'), message.encode('utf-8'), hashlib.sha256).hexdigest()

# 构造请求头
headers = {
    'CB-ACCESS-KEY': api_key,
    'CB-ACCESS-SIGN': signature,
    'CB-ACCESS-TIMESTAMP': timestamp,
    'Content-Type': 'application/json'
}

# 发送请求
response = requests.post(url, headers=headers, data=request_body)
print(response.json())

注意:有些语言的HMAC实现默认返回二进制数据,必须转成十六进制字符串才能作为签名,别直接用二进制值。

5. API环境是否匹配

如果你用的是测试网(Sandbox)的API密钥,必须请求https://api.sandbox.coinbase.com;生产环境密钥对应https://api.coinbase.com。环境不匹配也会导致签名验证失败。

如果以上排查都没问题,建议把你的签名生成步骤(隐去敏感信息)和请求头贴出来,这样更容易定位细节问题。

内容的提问来源于stack exchange,提问作者Dylan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:22:14