Sign inGet Started

购买和释放号码

购买号码需要两次调用:先搜索某个国家的在售号码,然后下单购买你想要的号码。所有操作都需要一个具有 numbers 范围的 API 密钥,且组织中的首次购买需要完成身份验证。

搜索国家

搜索始终限定在一个国家内,因此 country_code 是必填项。可以通过 number_type、capabilities 或国内号码的 prefix 进一步缩小范围。

// The search is always country-scoped, so country_code is required.
const page = await bird.numbers.available.list({
  country_code: "GB",
  capabilities: ["sms", "voice"],
});
for (const candidate of page.data) {
  console.log(candidate.number, candidate.number_type);
}

使用与你的密钥 bk_{region}_ 前缀匹配的区域主机:https://us1.platform.bird.com 或 https://eu1.platform.bird.com。

每条结果描述了该号码的信息:

代码示例
{
  "data": [
    {
      "number": "+447700900123",
      "country_code": "GB",
      "number_type": "mobile",
      "capabilities": ["sms", "voice"],
      "pricing": {
        "setup_price": { "amount": "0.00995", "currency_code": "USD" },
        "recurring_price": { "amount": "0.00995", "currency_code": "USD" },
        "recurring_period": { "unit": "month", "count": 1 },
        "intervals_per_charge": 12
      }
    }
  ],
  "next_cursor": null,
  "prev_cursor": null
}

每条结果还包含一个 pricing 对象,其中是你所在组织的税前价格,以账单币种计价:

  • setup_price 在你下单购买号码时一次性收取。公布的费用为零时,其 amount 为 "0"。无开通费时,该字段本身为 null;recurring_price 为 null 时也是如此,因为该号码无法下单。
  • recurring_price 是每 recurring_period 的费率。
  • intervals_per_charge 表示一次计费覆盖多少个 recurring_period。税前周期性费用等于 recurring_price 乘以 intervals_per_charge,在号码分配到你的工作区时以及每次续费时收取。对于需要等待运营商处理的订单,号码在订单完成时分配。recurring_period 为一个月且 intervals_per_charge: 12 时,一次计费 12 个月。

API 参考文档展示了一个包含价格的示例结果。包含 pricing.recurring_price: null 的搜索结果不会提供周期性价格。请在下单前联系销售,获取该国家和号码类型的定价。

控制面板和 API 使用相同的组织价格,包括到账单币种的汇率换算。读取价格不会锁定报价:在后续扣费之前发生的资费或汇率变动可能导致金额变化。如果价格查询失败,搜索将返回 503 和 E14009。请使用指数退避重试查询;查询失败绝不代表该号码不收费。

我们自有库存会优先返回并正常分页。最后一页可能包含运营商实时提供的号码,因此刚刚列出的号码在你下单时可能已经被买走。

要在下单前确认号码仍然可用,请通过 GET /v1/numbers/available/{number} 重新读取该号码。返回 404 表示该号码当前不可购买,无论是运营商已撤回还是我们自有库存已将其预留。重新检查与搜索共用同一个 numbers_availability 请求速率限制,因此只对即将下单的候选号码做重新检查,而不是对每个结果都检查一遍。

下单购买号码

将搜索结果中的号码传给 POST /v1/numbers/orders。关于重试保护,请参阅幂等性。

const order = await bird.numbers.orders.create({ number: "+447700900201" });
// Most orders finish inside the request. One that has to wait on a carrier
// comes back without a number_id. Poll it until it is completed or failed.
if (order.status === "completed") {
  console.log("allocated as", order.number_id);
} else {
  console.log("still", order.status, "; poll", order.id);
}

大多数订单在请求内即可完成,返回 201,号码已归你所有:

代码示例
{
  "id": "nor_01m0da22b0e39anhzyhtw3gzdg",
  "number": "+447700900123",
  "country_code": "GB",
  "number_type": "mobile",
  "status": "completed",
  "number_id": "nda_7eqywfwzxwa1za9n8wp7e1xkr8",
  "failure_reason": null,
  "completed_at": "2026-08-19T15:25:56.479320Z",
  "created_at": "2026-08-19T15:25:56.448051Z",
  "updated_at": "2026-08-19T15:25:56.479320Z"
}

number_id 是后续所有操作的标识:读取号码和释放号码。

轮询未完成的订单

需要等待运营商处理的订单会返回 202,此时 number_id 仍为 null。反复读取该订单,直到 status 变为 completed 或 failed。

const order = await bird.numbers.orders.get("nor_01krdgeqcxet5s7t44vh8rt9mg");
// failure_reason says what went wrong, and only ever on a failed order.
console.log(order.status, order.failure_reason ?? "");

订单依次经过 charging、ordering 和 pending,然后最终确定。当状态为 failed 时,failure_reason 会用简明语言说明失败原因。已扣除的开通费不会退还,因此失败的订单可能仍会产生费用;如遇此情况请联系支持团队。

释放号码

释放号码会停止周期性扣费,你也将无法再使用该号码。只有 dedicated 状态的号码才能被释放,释放后的号码不会立即重新上架出售。

// Releasing stops the recurring charge and the number stops working for you.
// Only a dedicated number can be released; a shared one answers E14002.
await bird.numbers.release("nda_01krdgeqcxet5s7t44vh8rt9mg");

释放成功后返回 204,无响应体。如果希望保留号码直到已付费周期结束,请改用取消操作:管理你的电话号码对两种方式均有说明。

订单被拒绝时

四种拒绝原因涵盖了几乎所有购买失败的情况。

402 加 E03000 表示钱包余额不足以支付该号码。充值后重新下单。此时不会创建订单,因此不会产生扣费。

412 表示该组织尚未完成首次购买所需的身份验证。完成验证后重试。

409 加 E14000 表示在你选择期间该号码已被他人购买。重新搜索并选择另一个号码。

409 加 E14001 表示你有太多订单仍在处理中。等待其中一个完成后再下单。

后续步骤

继续查看此主题的文档、指南和示例。