API 文档
API 让您的应用服务器获得与个人中心相同的能力:币种目录与汇率、地址余额与历史、新地址、手续费计算与转账发送,以及到账通知。
目录
API 地址: https://api.coinvertus.net/v1
通用规则
- 调用即向 API 地址加调用名发送 POST,例如 /v1/assets。路径中的 {COIN} 为 assets 中的代码或币种 ID,{TASK_ID} 为任务的 task_id。
- 请求体为不超过 64 KB 的 JSON 对象;无参数的调用可以不带请求体。成功响应直接返回对象或列表,没有外层包装。
- 金额为带小数点的字符串,以币为单位,不带末尾的零。时间为 UTC 的 ISO 8601 字符串,例如 2026-10-04T12:00:00Z。
- network 为 assets 中的网络代码。币种存在于多个网络时必须填写(否则返回 400 A014)。
- 错误文本使用 Accept-Language 中的语言(俄语、英语、中文);请根据错误代码做判断。
| 调用 | 密钥权限 | 说明 |
|---|---|---|
POST /v1/assets | 无需密钥(若调用对访客开放) | API 支持的币种与网络及其能力。 |
POST /v1/rates | 无需密钥(若调用对访客开放) | 币种与代币汇率,分页返回。 |
POST /v1/rate/{COIN} | 无需密钥(若调用对访客开放) | 单个币种的汇率。 |
POST /v1/checkaddress/{COIN} | 无需密钥(若调用对访客开放) | 校验地址;带密钥时可知是否为您的地址。 |
POST /v1/paybalance | read | 以 USD 计的支付余额。 |
POST /v1/getbalance[/{COIN}] | read | 按币种和网络的余额。 |
POST /v1/addresses/{COIN} | read | 币种已发放的地址。 |
POST /v1/txinfo/{COIN} | read | 按 txid 查询您地址的交易。 |
POST /v1/transactions/{COIN} | read | 您地址的交易历史。 |
POST /v1/getnewaddress/{COIN} | addresses | 新地址或新标签。 |
POST /v1/getfee/{COIN} | send | 网络手续费与服务费。 |
POST /v1/spendinfo/{COIN} | send | 资金将从哪些地址转出。 |
POST /v1/preparetx/{COIN} | send | 发送计划。 |
POST /v1/posttx | send | 确认计划并创建任务。 |
POST /v1/task/{TASK_ID} | send | 发送任务的状态。 |
POST /v1/task/{TASK_ID}/cancel | send | 取消排队中的任务。 |
快速开始
- 请在个人中心连接身份验证器应用或验证邮箱:API 密钥只能凭验证码创建和修改。
- 在“API 密钥”中创建密钥(每个账户最多 10 个):勾选权限,并填写服务器的 IP 地址或子网白名单——来自其他地址的请求将返回 403 A005。
- 保存密钥 ID(ak_…)和密钥:密钥只显示一次。遗失后请在密钥页面重新签发。
- 如需通知,请在“Webhook”中填写地址并保存其密钥(whsec_…)。
- 发送前请为支付余额充值:服务费从中扣除。
| 密钥权限 | 说明 |
|---|---|
read | 余额、地址、交易历史、支付余额。 |
addresses | 发放新地址。 |
keys | 新地址的私钥(getnewaddress 中的 priv),需同时具有 addresses 权限。 |
send | 计算手续费、准备并发送转账、任务。 |
请求签名
带密钥的请求包含两个请求头。v1 为字符串“t.POST.路径.请求体”的十六进制 HMAC-SHA256,密钥为 API 密钥的 secret。路径与请求地址一致,从 /v1/ 开始(如有查询字符串一并包含);请求体为您实际发送的字节,空请求体即空字符串。t 为以秒计的 Unix 时间:与服务器时钟相差超过 5 分钟的签名会被拒绝。
| 请求头 | 说明 |
|---|---|
X-CVC-Key | 密钥 ID:ak_ 加 24 位十六进制字符。 |
X-CVC-Signature | 签名:t=<Unix 时间>,v1=<签名>。 |
t = 1789647000
msg = 1789647000.POST./v1/getbalance/DOGE.{"network":"dogecoin-mainnet"}
v1 = hex(HMAC-SHA256(secret, msg))
X-CVC-Key: ak_0f1e2d3c4b5a69788796a5b4
X-CVC-Signature: t=1789647000,v1=<v1>CVC 可以让参考类调用(assets、rates、rate、checkaddress)无需密钥:此类请求不带两个请求头,限额按 IP 地址计算。调用未对访客开放时返回 401 A004。
响应与错误
拒绝时返回 HTTP 状态码和 error 主体:code 为错误代码,message 为文本,fields 为未通过校验的请求字段(如已知)。
{
"error": {
"code": "A014",
"message": "请指定 network:该币种存在于多个网络中。",
"fields": [
"network"
]
}
}不带调用的 API 地址请求返回 200 和 {"status":"OK","version":"…"}(应用版本),可用于检查可用性。不存在的调用返回 404 和 {"status":"error","code":404}。
| HTTP 状态码 | 错误代码 | 含义 |
|---|---|---|
400 | A002 | 请求无效:请求体必须是不超过 64 KB 且字段有效的 JSON 对象。 |
401 | A003 | 密钥或请求签名验证失败。 |
401 | A004 | 此调用需要 API 密钥。 |
403 | A005 | 请求来自密钥 IP 白名单之外的地址。 |
403 | A006 | 密钥缺少该调用所需的权限。 |
403 | A007 | 您的套餐不支持此调用。 |
404 | 404 | 没有此调用:响应体为 {"status":"error","code":404},不含 error 字段。 |
503 | A009 | 调用已关闭、网络或节点暂时不可用,或地址被上一笔转账占用。请稍后重试。 |
429 | A010 | 超出请求限额。请在 Retry-After 请求头给出的秒数后重试。 |
500 | A011 | 内部错误,请稍后重试。 |
405 | A012 | 请使用 POST 方法。 |
404 | A013 | 未找到该币种。 |
400 | A014 | 请指定 network:该币种存在于多个网络中。 |
404 | A015 | 未找到交易。 |
403 | A016 | 该网络中通过 API 发放的地址配额已用完。 |
409 | A018 | 资金不足以支付金额和网络手续费。 |
422 | A019 | 暂不支持通过 API 计算此币种的费用和发送。 |
409 | A020 | 支付余额不足以支付服务费。请充值余额。 |
404, 409 | A021 | 发送方案未找到、已过期或已失效。请重新准备发送。 |
404 | A022 | 未找到任务。 |
409 | A024 | 任务已无法取消:只能取消排队中的任务。 |
限额
每个调用有各自的每秒请求限额(默认 1 次),以及按您的套餐计算的每分钟和每月限额;此外还适用套餐中的账户总上限。月份按 UTC 自然月计算。超出时返回 429 A010 并带 Retry-After 请求头。访客按 IP 地址计算(IPv6 按 /64 网段)。访问网络节点的调用(getfee、spendinfo、preparetx,Monero 和 Zcash 还包括 checkaddress 与 getnewaddress)在部分网络上另有限制:同一密钥在每个网络中每隔数秒最多一次,并且整个网络每分钟的此类调用有总上限。拒绝时同样返回 429 A010 并带 Retry-After。
参考类调用
assets
API 支持的“币种 × 网络”组合及其能力列表。组合很少变化——可以在本地保存目录并每天更新一次。
[
{
"coin": "DOGE",
"name": "Dogecoin",
"network": "dogecoin-mainnet",
"network_name": "Dogecoin",
"testnet": false,
"type": "coin",
"contract": null,
"decimals": 8,
"formats": [
"base58"
],
"confirmations": 6,
"min_amount": null,
"can_send": true,
"multi_recipient": true,
"tag": false,
"fee_levels": [
"fast",
"normal",
"low"
]
}
]| 字段 | 说明 |
|---|---|
coin | 币种或代币的代码——可作为 {COIN} 传入。 |
network, network_name, testnet | network 使用的网络代码、网络名称及是否为测试网。 |
type, contract | coin 为网络原生币,token 为代币,合约地址在 contract 中。 |
decimals | 金额的小数位数。 |
formats | 可在 getnewaddress 中请求的地址格式。 |
confirmations | 交易变为 confirmed 所需的确认数。 |
can_send | 该组合可通过 API 发送:getfee、preparetx、posttx。 |
multi_recipient | 一笔交易可包含多个收款方。 |
tag | 收款方可能需要目标标签——to[].tag。 |
fee_levels | getfee 返回、preparetx 的 fee 参数接受的手续费档位:按区块目标估算的 UTXO 网络为 fast、normal 和 low,其他网络仅 normal;空列表表示不支持发送。 |
min_amount | 保留字段:min_amount 目前为 null。 |
rates, rate/{COIN}
目录中币种与代币的 USD、EUR、RUB、CNY、INR 汇率,每页 100 条(page 从 1 开始;空页表示结束)。coins 为可选的代码或 ID 列表,最多 100 个。无汇率时为 null,updated_at 为汇率时间。rate/{COIN} 返回其中一条。
{
"coin": "DOGE",
"id": "dogecoin",
"name": "Dogecoin",
"usd": "0.2251",
"eur": "0.2089",
"rub": "18.42",
"cny": "1.6237",
"inr": "18.91",
"updated_at": "2026-09-17T12:10:00Z"
}checkaddress/{COIN}
在组合所属网络中校验地址。请求:address、network。响应:valid、address(规范形式)、coin、network、format。使用具有 read 权限的密钥时,还会返回 is_mine(地址是否发放给您的账户)和 balance(其已确认余额);无密钥或他人地址时为 null。
余额与历史
paybalance
扣除服务费所用的支付余额:usd 为可用金额,reserved 为提现申请和未完成任务的服务费中冻结的金额;auto_topup、threshold、topup_amount 为自动充值设置(未设置阈值时为 false 和 null)。
getbalance[/{COIN}]
不带 {COIN} 时返回您拥有地址的组合;带 {COIN} 时返回该币种的所有网络,或在指定 network 时返回一个。balance 为已确认余额,pending 为未确认的入账,available 为当前可发送金额,fiat 为 balance 的五种货币价值,addresses 为地址数量,stale 表示数据可能落后于网络。
[
{
"coin": "DOGE",
"network": "dogecoin-mainnet",
"type": "coin",
"balance": "250",
"pending": "0",
"available": "250",
"fiat": {
"usd": "56.28",
"eur": "52.23",
"rub": "4605",
"cny": "405.93",
"inr": "4727.5"
},
"addresses": 3,
"updated_at": "2026-09-17T12:10:00Z",
"stale": false
}
]addresses/{COIN}
组合已发放的地址,按发放顺序,每页 100 个(page):address、format、label、balance、pending、created_at。代币则返回其网络中的地址及代币余额。
txinfo/{COIN}, transactions/{COIN}
txinfo 按 txid(与网络浏览器显示的格式一致)返回您地址的交易。从 mempool 中掉落的交易会被监控删除:查询返回 404 A015,tx.dropped Webhook 会通知此事。
transactions 返回您在该组合中的地址历史,每页 100 条,最新在前,未确认的排在最前。筛选:address 为您的某个地址,from 和 to 为交易时间(含边界)。新交易会使分页偏移——对账时使用 from/to 时间窗口更方便。
{
"txid": "c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0",
"coin": "DOGE",
"network": "dogecoin-mainnet",
"direction": "in",
"status": "confirmed",
"confirmations": 6,
"block": 5912340,
"time": "2026-09-17T12:04:00Z",
"transfers": [
{
"address": "DLp4hPWtqM8sQZoyk2vRj3TfGcX5nA7bUe",
"direction": "in",
"amount": "250",
"tag": null
}
],
"fee": null,
"fee_coin": "DOGE"
}| 字段 | 说明 |
|---|---|
direction | in 为入账,out 为从您的地址转出。 |
status | new 为等待确认,confirmed 为确认数不少于组合的 confirmations,failed 为网络拒绝了交易并扣除了网络手续费。 |
block, confirmations, time | 区块、确认数和交易时间;交易仍在 mempool 中时 block 和 time 为 null。 |
transfers | 按地址和方向汇总的您地址上的资金变动。UTXO 的支出为整笔输入,找零单独作为一行 in。tag 为入账转账的目标标签。 |
fee, fee_coin | 转出交易的网络手续费及其币种(代币则为网络原生币)。 |
发放地址
getnewaddress/{COIN} 在组合所属网络中发放新地址。请求:network、format(组合 formats 之一)、label(最多 190 个字符的备注)、priv。在使用目标标签的网络中账户只有一个地址——调用会为其发放新的 tag。每个账户在每个网络通过 API 发放的地址配额由 CVC 设定,超出时返回 403 A016。
{
"coin": "DOGE",
"network": "dogecoin-mainnet",
"address": "D8vFz4p1L37jdg47HXKtSHA5uYLYxbGgPD",
"format": "base58",
"tag": null,
"privkey": null
}priv: true(需要 keys 权限)时响应包含 privkey:以 AES-256-GCM 加密的私钥。加密密钥为 HMAC-SHA256(API 密钥 secret, “privkey”) 的原始字节,值为 base64(12 字节 nonce ‖ 密文 ‖ 16 字节标签)。在私钥属于节点钱包的网络中,privkey 始终为 null。
发送流程
- getfee:fast、normal、low 三档网络手续费及服务费;spendinfo:资金将从哪些地址转出。
- preparetx:转账计划,包括来源、收款方、手续费和步骤。计划不预留任何资金,有效期 5 分钟(expires_at)。
- 核对计划并确认:调用 posttx,传入 prepare_id 和 confirm = HMAC-SHA256(密钥 secret, “key_id.fingerprint.prepare_confirm.prepare_time”),其中 key_id 为准备该计划的密钥 ID。
- posttx 将任务加入队列并扣除服务费;队列会在数秒内发送转账。结果可通过 task/{TASK_ID} 或 task.done Webhook 获取。
| 字段 | 说明 |
|---|---|
to | 收款方:address 和 amount;tag 为目标标签,comment 为给收款方的文本,最多 120 个字符,仅限支持的网络。多个收款方(最多 100 个)仅限带 multi_recipient 的组合;使用 send_all 时只能有一个不带 amount 的收款方。 |
from | 您的来源地址(address);不填时自动选择。在账户模型网络中只能一个地址。 |
order | 来源选择顺序:desc(默认)先用大额地址,asc 先用小额地址。 |
fee | preparetx:fast、normal(默认)或 low;在 UTXO 网络中还可以是以 fee_rate_unit 为单位的费率数值。账户模型网络仅支持 normal;需要支付能量的代币还可选 rent 或 burn。 |
change | preparetx,UTXO 网络:找零去向——auto(默认,最大一笔输入的地址)、new(新地址)或该网络中您自己的地址。 |
send_all | preparetx:true 表示将来源中的全部资金扣除手续费后发出。 |
getfee 与 spendinfo
getfee 使用相同的 to、from、order。fee_coin 为网络手续费的币种(代币则为网络原生币);fast、normal、low 为 amount 及五种货币,若网络没有该档位或在该档位下金额加手续费不够则为 null(所有档位都不够时返回 409 A018);service_fee_usd 为服务费;extra 为额外费用。
{
"coin": "DOGE",
"network": "dogecoin-mainnet",
"fee_coin": "DOGE",
"fast": {
"amount": "0.04452",
"usd": "0.2",
"eur": "0.01",
"rub": "0.5",
"cny": "0.04",
"inr": "0.47"
},
"normal": {
"amount": "0.02226",
"usd": "0.1",
"eur": "0.01",
"rub": "0.5",
"cny": "0.04",
"inr": "0.47"
},
"low": null,
"service_fee_usd": "0.10",
"extra": []
}extra.type | 含义 |
|---|---|
gas | 代币地址上的网络原生币不足:amount 将从您的另一个地址转入,network_fee 为该笔转账的手续费。 |
rent | 不带 provider:在收款方尚无代币账户时为其创建账户。 |
burn, rent | 带 provider:支付代币能量的方式——燃烧(burn)或租用(rent);selected 标出 fee normal 会选择的方式。 |
spendinfo 使用 to 和 order。sources 为按 order 排序的有资金地址:address、balance(可用)、locked(被未完成转账占用)、use(发送时将从该地址取用的金额);enough 表示是否足够。代币的 use 为代币金额,手续费由 getfee 和 preparetx 检查。
preparetx:发送计划
请求:network、to、from、order、fee、change、send_all。响应为计划以及用于在 posttx 中确认的数据。支付余额不足以支付服务费时返回 409 A020。
{
"prepare_id": "prep_9a3f0c7d21b84e65f0a1c2d3",
"prepare_confirm": "5c0e8d1f7a2b4c6d9e3f1a0b2c4d6e8f",
"prepare_time": 1789647000,
"expires_at": "2026-09-17T12:15:00Z",
"fingerprint": "0995342725a2b11aa2260e7e84e6394754eef9dcc7412a222e2952b9d9589345",
"coin": "DOGE",
"network": "dogecoin-mainnet",
"tx": {
"sources": [
{
"address": "DLp4hPWtqM8sQZoyk2vRj3TfGcX5nA7bUe",
"amount": "150.5"
}
],
"recipients": [
{
"address": "D8vFz4p1L37jdg47HXKtSHA5uYLYxbGgPD",
"amount": "100"
}
],
"change": {
"address": "DLp4hPWtqM8sQZoyk2vRj3TfGcX5nA7bUe",
"amount": "50.47774"
},
"network_fee": "0.02226",
"fee_coin": "DOGE",
"fee_rate": "100",
"fee_rate_unit": "koinu/vB",
"size": 226,
"replaceable": false
},
"steps": [
{
"type": "send"
}
],
"service_fee_usd": "0.10"
}| 字段 | 说明 |
|---|---|
tx.sources | 来源地址以及每个地址转出的金额(含网络手续费)。 |
tx.recipients | 收款方及金额;在使用标签或备注的网络中包含 tag 和 comment。 |
tx.change | UTXO 找零:地址和金额;无找零时为 null。 |
tx.network_fee, tx.fee_coin | 网络手续费及其币种。 |
tx.fee_rate, tx.fee_rate_unit, tx.size, tx.replaceable | UTXO 网络:费率及其单位、交易大小,以及能否被更高手续费的交易替换。 |
tx.fee_payer, tx.rent | 由您的另一个地址在同一笔交易中支付手续费的代币:该地址以及为收款方创建账户的费用。 |
steps | 执行步骤:gas 为先补充燃料(from、to、amount、network_fee),rent 为租用能量(provider、energy、cost),send 为转账本身。 |
expires_at, fingerprint | 计划有效期及其指纹:只能在 expires_at 之前确认计划。 |
posttx 与任务
posttx 传入 prepare_id 和 confirm,返回任务对象。使用相同 prepare_id 重复调用会返回同一任务,计划过期后亦然,因此连接中断后可以安全重试。他人的计划返回 404 A021,已过期返回 409 A021,confirm 错误返回 400 A002。task/{TASK_ID} 返回同样的对象。
{
"task_id": "task_6f1c2a9b0d4e8f7a3c5b1d20",
"task_info": "confirmed",
"task_start": "2026-09-17T12:10:00Z",
"task_sent": "2026-09-17T12:10:04Z",
"task_done": "2026-09-17T12:20:12Z",
"prepare_id": "prep_9a3f0c7d21b84e65f0a1c2d3",
"coin": "DOGE",
"network": "dogecoin-mainnet",
"txid": "b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7",
"gas_txid": null,
"confirmations": 6,
"error_code": null,
"tx": {
"sources": [
{
"address": "DLp4hPWtqM8sQZoyk2vRj3TfGcX5nA7bUe",
"amount": "150.5"
}
],
"recipients": [
{
"address": "D8vFz4p1L37jdg47HXKtSHA5uYLYxbGgPD",
"amount": "100"
}
],
"change": {
"address": "DLp4hPWtqM8sQZoyk2vRj3TfGcX5nA7bUe",
"amount": "50.47774"
},
"network_fee": "0.02226",
"fee_coin": "DOGE",
"fee_rate": "100",
"fee_rate_unit": "koinu/vB",
"size": 226,
"replaceable": false
},
"service_fee_usd": "0.1"
}task_info | 含义 |
|---|---|
queue | 排队中;任务可以取消。 |
processing | 正在发送。 |
gas | 等待代币燃料补充交易确认。 |
rent | 等待能量租用。 |
sent | 已上链,等待确认。 |
unknown | 发送结果未知:节点未响应。请勿重复转账——对账会确定结果,任务会自行继续。 |
confirmed | 已确认。 |
failed | 未完成——原因见 error_code。 |
dropped | 交易未获确认即从网络中掉落。 |
cancelled | 已由客户端取消。 |
| 字段 | 说明 |
|---|---|
task_start, task_sent, task_done | 入队、上链和到达最终状态的时间;尚未发生时为 null。 |
txid, gas_txid, confirmations | 转账交易、燃料补充交易及确认数;发送前为 null。 |
error_code | 任务未完成时的原因代码,否则为 null。 |
tx, service_fee_usd | 来自 preparetx 的计划及该任务扣除的服务费。 |
error_code | 含义 |
|---|---|
A009 | 网络或节点不可用超过 30 分钟,或发送结果未知。 |
A018 | 发送时地址上的资金不足。 |
A021 | 计划已过时(preparetx 之后余额、手续费或地址发生变化)或账户被冻结。 |
A023 | 网络拒绝了交易;已扣除网络手续费。 |
A025 | 能量租用失败。 |
task/{TASK_ID}/cancel 取消处于 queue 的任务——在首次尝试之前或两次重试之间;已发送燃料或已下单租用后无法取消。之后调用返回 409 A024。对已取消的任务重复调用会返回该任务。
各网络特点
- UTXO 网络:支持多个收款方,fast、normal、low 档位或自定义费率,找零通过 change 指定;来源为您地址上的输入。
- 账户模型网络:一个来源地址和一个收款方,仅 normal。有未完成转账的地址在其确认前处于占用状态——任务最多等待 30 分钟。
- 使用目标标签的网络(assets 中的 tag):to[].tag 会传给收款方;转入您地址的入账通过 transfers 中的 tag 区分,getnewaddress 会为同一地址发放新标签。
- 支持转账备注的网络:to[].comment 为最多 120 个字符的文本;其他网络会拒绝该字段(400 A002)。
- 代币:手续费以网络原生币从同一地址支付。若不足,计划以 gas 步骤开始:从您在该网络中最大的空闲地址补充,补充确认后再发送代币。
- 需要支付能量的代币:fee normal 会向最便宜的已连接服务商租用,否则燃烧;rent 或 burn 为手动选择。租用失败——failed A025。服务商在账户设置的“助手”标签页中连接。
- 由您网络原生币余额最多的地址在同一笔交易中支付手续费和收款方账户创建费用的代币:tx 中包含 fee_payer 和 rent,没有 gas 步骤。
- 隐私网络:从一个地址发送,getfee 为上限估算,准确手续费见 preparetx,不提供 privkey;通过节点钱包发送最多需要几分钟。
服务费与支付余额
服务费按套餐计算:按 USD 金额的百分比,设有最低和最高值;getfee 和 preparetx 会显示(service_fee_usd)。在 posttx 时从支付余额中扣除;若转账未上链、掉落或任务被取消则退还。已确认的转账以及被网络拒绝的转账(failed A023)不退还。
为避免因余额不足导致发送停滞,请在个人中心开启自动充值(支付余额 → 自动充值);余额低于阈值时 paybalance.low Webhook 会提醒您。
回调通知(Webhook)
Webhook 地址在个人中心的“Webhook”中设置:https 地址,必要时可填写 IP 和 Host。whsec_… 密钥只显示一次;检查按钮会发送 ping。Webhook 仅在包含该功能的套餐中可用。
通知为带 JSON 正文的 POST 请求。10 秒内任何 2xx 响应即为成功。否则分别在 1 分钟、5 分钟、30 分钟、2 小时、6 小时和 24 小时后重试。不跟随重定向,响应最多读取 64 KB。
| 请求头 | 说明 |
|---|---|
X-CVC-Event | 事件名称,与正文中的 event 相同。 |
X-CVC-Delivery | event_id 和尝试次数。 |
X-CVC-Signature | 签名:t=<Unix 时间>,v1=<签名>。 |
v1 为字符串“t.请求体”的十六进制 HMAC-SHA256,密钥为 Webhook 密钥(whsec_…)。请使用收到的原始字节(在解析 JSON 之前),如果 t 与您的时钟相差超过 5 分钟则拒绝该通知。
同一通知可能到达两次,每个 event_id 只处理一次。不保证送达顺序:不要因较早的通知回退已付款订单。
| 事件 | 发送时机 |
|---|---|
tx.new | 您地址的新交易。在不监控 mempool 的网络中,会在第一次确认时到达。 |
tx.confirmed | 交易已被网络确认或拒绝——请查看 status。 |
tx.dropped | 已通过 tx.new 通知的交易未获确认即从网络中掉落。 |
task.done | 发送任务到达最终状态:confirmed、failed、dropped 或 cancelled。 |
paybalance.low | 支付余额低于自动充值阈值:自动充值已关闭(reason 为 no_autotopup)或执行失败(autotopup_failed)。 |
ping | 来自账户的测试通知。 |
开启 Webhook 之前发生的交易不会推送。tx.* 主体为 transaction 对象(与 txinfo 相同);task.done 为 task 对象;paybalance.low 为 reason 和 paybalance 对象。
{
"event": "tx.new",
"event_id": "evt_0123456789abcdef01234567",
"created_at": "2026-09-17T12:10:00Z",
"transaction": {
"txid": "c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0",
"coin": "DOGE",
"network": "dogecoin-mainnet",
"direction": "in",
"status": "confirmed",
"confirmations": 6,
"block": 5912340,
"time": "2026-09-17T12:04:00Z",
"transfers": [
{
"address": "DLp4hPWtqM8sQZoyk2vRj3TfGcX5nA7bUe",
"direction": "in",
"amount": "250",
"tag": null
}
],
"fee": null,
"fee_coin": "DOGE"
}
}{
"event": "task.done",
"event_id": "evt_89abcdef0123456789abcdef",
"created_at": "2026-09-17T12:20:12Z",
"task": {
"task_id": "task_6f1c2a9b0d4e8f7a3c5b1d20",
"task_info": "confirmed",
"task_start": "2026-09-17T12:10:00Z",
"task_sent": "2026-09-17T12:10:04Z",
"task_done": "2026-09-17T12:20:12Z",
"prepare_id": "prep_9a3f0c7d21b84e65f0a1c2d3",
"coin": "DOGE",
"network": "dogecoin-mainnet",
"txid": "b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7",
"gas_txid": null,
"confirmations": 6,
"error_code": null,
"tx": {
"sources": [
{
"address": "DLp4hPWtqM8sQZoyk2vRj3TfGcX5nA7bUe",
"amount": "150.5"
}
],
"recipients": [
{
"address": "D8vFz4p1L37jdg47HXKtSHA5uYLYxbGgPD",
"amount": "100"
}
],
"change": {
"address": "DLp4hPWtqM8sQZoyk2vRj3TfGcX5nA7bUe",
"amount": "50.47774"
},
"network_fee": "0.02226",
"fee_coin": "DOGE",
"fee_rate": "100",
"fee_rate_unit": "koinu/vB",
"size": 226,
"replaceable": false
},
"service_fee_usd": "0.1"
}
}{
"event": "paybalance.low",
"event_id": "evt_456789abcdef0123456789ab",
"created_at": "2026-09-17T12:10:00Z",
"reason": "no_autotopup",
"paybalance": {
"usd": "3.2",
"reserved": "0.1",
"auto_topup": false,
"threshold": "5",
"topup_amount": "20"
}
}PHP 示例
签名调用、发送计划及其确认:
<?php
const CVC_API = 'https://api.coinvertus.net/v1';
function cvcCall(string $method, array $params = []): array
{
$keyId = getenv('CVC_API_KEY_ID');
$secret = getenv('CVC_API_SECRET');
$path = '/v1/' . $method;
$body = $params === [] ? '' : json_encode($params, JSON_UNESCAPED_SLASHES);
$t = time();
$v1 = hash_hmac('sha256', $t . '.POST.' . $path . '.' . $body, $secret);
$curl = curl_init(CVC_API . '/' . $method);
curl_setopt_array($curl, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $body,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'X-CVC-Key: ' . $keyId,
'X-CVC-Signature: t=' . $t . ',v1=' . $v1,
],
]);
$response = json_decode((string) curl_exec($curl), true);
$status = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
if ($status !== 200) {
throw new RuntimeException($status . ' ' . ($response['error']['code'] ?? '') . ' ' . ($response['error']['message'] ?? ''));
}
return $response;
}
$balances = cvcCall('getbalance/DOGE');
$plan = cvcCall('preparetx/DOGE', [
'to' => [['address' => 'D8vFz4p1L37jdg47HXKtSHA5uYLYxbGgPD', 'amount' => '100']],
]);
// Проверьте план: получатели, network_fee, service_fee_usd — и подтвердите его.
$confirm = hash_hmac('sha256', getenv('CVC_API_KEY_ID') . '.' . $plan['fingerprint'] . '.'
. $plan['prepare_confirm'] . '.' . $plan['prepare_time'], getenv('CVC_API_SECRET'));
$task = cvcCall('posttx', ['prepare_id' => $plan['prepare_id'], 'confirm' => $confirm]);
// Итог — вебхук task.done или опрос task/{TASK_ID}.
$task = cvcCall('task/' . $task['task_id']);接收 Webhook:
<?php
$secret = getenv('CVC_API_WEBHOOK_SECRET');
$body = file_get_contents('php://input');
$t = null;
$signatures = [];
foreach (explode(',', $_SERVER['HTTP_X_CVC_SIGNATURE'] ?? '') as $pair) {
[$name, $value] = array_pad(explode('=', trim($pair), 2), 2, '');
if ($name === 't') {
$t = $value;
} elseif ($name === 'v1') {
$signatures[] = strtolower($value);
}
}
$expected = hash_hmac('sha256', $t . '.' . $body, $secret);
$valid = $t !== null && ctype_digit($t) && abs(time() - (int) $t) <= 300
&& array_filter($signatures, fn (string $v1): bool => hash_equals($expected, $v1)) !== [];
if (!$valid) {
http_response_code(400);
exit;
}
$hook = json_decode($body, true);
if (!$events->remember($hook['event_id'])) {
http_response_code(200);
exit;
}
switch ($hook['event']) {
case 'tx.new':
case 'tx.confirmed':
case 'tx.dropped':
$ledger->apply($hook['transaction']);
break;
case 'task.done':
$payouts->finish($hook['task']['task_id'], $hook['task']['task_info'], $hook['task']['txid']);
break;
case 'paybalance.low':
$alerts->notify($hook['reason'], $hook['paybalance']['usd']);
break;
}
http_response_code(200);解密 getnewaddress 返回的 privkey:
<?php
$raw = base64_decode($response['privkey']);
$key = hash_hmac('sha256', 'privkey', getenv('CVC_API_SECRET'), true);
$privkey = openssl_decrypt(substr($raw, 12, -16), 'aes-256-gcm', $key, OPENSSL_RAW_DATA,
substr($raw, 0, 12), substr($raw, -16));示例已简化:遇到 429 和 503 时请间隔后重试,并按错误代码处理错误。