mcpField
P
phone-numbers

phone-numbers

github.com/zavudev其他1238 次安装2 天前更新
代码仓库

关于 phone-numbers

phone-numbers 是通过 Zavu API 搜索、购买和管理电话号码的技能,面向需要处理号码类型、运营商监管要求和 Sender 分配的开发者。

主要功能

  1. 01按国家和类型搜索号码
  2. 02购买和管理号码
  3. 03查询运营商要求
  4. 04提交地址和文件
  5. 05将号码分配给 Sender

适用场景

  1. 01查找符合地区或号码模式的号码
  2. 02提交合规资料并购买号码
  3. 03跟踪号码监管审批
  4. 04将号码连接到 Sender

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/zavudev/zavu-skills --skill phone-numbers

安装后在 Claude Code 中输入/phone-numbers确认已加载。

详细介绍

电话号码

适用场景

在构建用于搜索、购买或管理电话号码的代码时使用此技能。涵盖可用号码搜索、购买、监管要求和发送方分配。

搜索可用号码

const result = await zavu.phoneNumbers.searchAvailable({
  countryCode: "US",
  type: "local",
  contains: "555",
  limit: 10,
});

for (const number of result.items) {
  console.log(number.phoneNumber);       // +15551234567
  console.log(number.friendlyName);      // (555) 123-4567
  console.log(number.locality);          // San Francisco
  console.log(number.capabilities);      // { sms: true, voice: true, mms: true }
  console.log(number.pricing.monthlyPrice); // 1.25
  console.log(number.pricing.isFreeEligible); // true (paid plans include one US number, once per account)
}

Python:

result = zavu.phone_numbers.search_available(
    country_code="US",
    type="local",
    contains="555",
    limit=10,
)
for number in result.items:
    print(number.phone_number, number.pricing.monthly_price)

Go:

result, err := client.PhoneNumbers.SearchAvailable(context.TODO(), zavudev.PhoneNumberSearchAvailableParams{
    CountryCode: "US",
    Type:        zavudev.PhoneNumberTypeLocal,
    Contains:    zavudev.String("555"),
    Limit:       zavudev.Int(10),
})
for _, number := range result.Items {
    fmt.Println(number.PhoneNumber, number.Pricing.MonthlyPrice)
}

Ruby:

result = client.phone_numbers.search_available(country_code: "US", type: "local", contains: "555", limit: 10)
result.items.each { |number| puts "#{number.phone_number} #{number.pricing.monthly_price}" }

PHP:

$result = $client->phoneNumbers->searchAvailable(
    countryCode: 'US', type: 'local', contains: '555', limit: 10,
);
foreach ($result->items as $number) {
    echo $number->phoneNumber . ' ' . $number->pricing->monthlyPrice . "\n";
}

购买电话号码

const result = await zavu.phoneNumbers.purchase({
  phoneNumber: "+15551234567",
  name: "Primary Line",
});
console.log(result.phoneNumber.id);     // pn_abc123
console.log(result.phoneNumber.status); // "active"

购买号码需要付费套餐。 免费套餐无法购买电话号码(API 会返回代码为 paid_plan_required 的 402)。付费套餐每个账户可免费获得一个号码,仅限一次:该号码必须是美国或加拿大号码(+1 号码),且月费不超过 $20。搜索结果中的 pricing.isFreeEligible 会标记符合条件的号码。

电话号码类型

类型描述
local地理号码,与某个城市或地区关联
national非地理号码,在全国范围内有效
mobile手机号码。在多个国家/地区,这是唯一有库存的类型;在某些市场中,也是唯一可接收 SMS 的类型
tollFree免费电话号码

管理电话号码

// List owned numbers
const numbers = await zavu.phoneNumbers.list({ status: "active" });
for (const pn of numbers.items) {
  console.log(pn.id, pn.phoneNumber, pn.status);
}

// Get details
const pn = await zavu.phoneNumbers.retrieve("pn_abc123");

// Rename
await zavu.phoneNumbers.update("pn_abc123", { name: "Support Line" });

// Assign to sender
await zavu.phoneNumbers.update("pn_abc123", { senderId: "snd_abc123" });

// Unassign from sender
await zavu.phoneNumbers.update("pn_abc123", { senderId: null });

// Release number (must not be assigned to a sender)
await zavu.phoneNumbers.release("pn_abc123");

监管要求

号码是否需要监管信息(地址、文件或文本),由运营商按每个号码决定,而不是依据固定的国家列表。购买前,系统会查询该确切号码的要求,不会提前收费。整个流程通过 API 完成:

  1. GET /v1/phone-numbers/requirements?phoneNumber=%2B4930123456&type=local(将 + 编码为 %2B;不编码的 + 也可以)。响应会列出购买该号码时需要验证的信息;如果无法解析该号码自身的要求,则返回其国家和 type 对应的列表。items 为空表示该号码无需提供信息,可直接购买。502 requirements_unavailable 表示查询失败:请重试,切勿将其视为“无需提供信息”(即使发生这种情况,美国和加拿大号码也会作为无需提供信息的号码出售)。
  2. 对于每个 requirementTypes[] 条目:address → 在同一项目中通过 POST /v1/addresses 创建一个地址(必须提供 firstName 和 lastName),并使用其 id;document → 上传一个文件(POST /v1/documents,见下文),并使用其 id;textual → 使用文本本身;action → 无需为其发送任何内容。每个 id 只提交一次。
  3. 购买时提供 type(提交监管要求时必填)和 regulatoryRequirements。SDK 尚不支持这些字段,因此请调用 REST:
curl -X POST https://api.zavu.dev/v1/phone-numbers \
  -H "Authorization: Bearer $ZAVUDEV_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "phoneNumber": "+4930123456",
    "type": "local",
    "regulatoryRequirements": [
      { "requirementType": "<requirementTypes[].id>", "fieldValue": "<address id>" },
      { "requirementType": "<requirementTypes[].id>", "fieldValue": "<document id>" }
    ]
  }'
  1. 号码会立即购买并计费,其 regulatoryStatus 为 "pending_review"。在 regulatoryStatus 变为 "approved" 之前,该号码无法发送消息或拨打电话。系统每 6 小时重新检查一次状态:轮询 GET /v1/phone-numbers/{phoneNumberId}。
  2. 将号码分配给发送方(通过 PATCH /v1/phone-numbers/{phoneNumberId} 设置 senderId),可以在审核通过前或之后进行。审核期间分配的号码会在获批后连接到该发送方,并会持续重试直至成功;通过 API 创建的发送方会在分配过程中设置为支持 SMS。rejected 状态的号码无法分配(400)。如果号码长时间处于 pending_review,请联系支持团队。

以下错误均不会产生任何费用:

响应含义
400 regulatory_compliance_required该号码需要提供信息,但未提交任何信息或无法复用已有信息。details.missingRequirements 会列出 { id, name, type }。
400 invalid_request缺少必需的 id、id 未知或重复、地址或文件不属于此项目或已被拒绝,或者无法将其提交审核。details 会指出相关要求。
400 number_unavailable该号码已不可用,或未列在所提交的 type 下。
502 requirements_unavailable无法查询要求。请重试。美国和加拿大号码不会返回此错误。

复用:你提交的信息会按号码所属国家和 type 保存在项目中。之后在该地区购买时,可以省略 regulatoryRequirements,但前提是已保存的信息仍涵盖该号码的所有要求,并且其中的地址和文件都属于该项目;否则会返回 400 regulatory_compliance_required。

// Requirements for a country and type (the SDK has no per-number variant yet;
// the purchase checks the exact number, so prefer the REST call in step 1)
const requirements = await zavu.phoneNumbers.requirements({
  countryCode: "DE",
  type: "local",
});

for (const req of requirements.items) {
  for (const rt of req.requirementTypes) {
    console.log(`${rt.id} ${rt.name}: ${rt.type} - ${rt.description}`);
  }
}
要求类型
类型说明
textual文本字段(姓名、企业名称)
address实际地址
document身份证明文件(护照、身份证等)
action要执行的操作
创建监管地址
const address = await zavu.addresses.create({
  firstName: "John",
  lastName: "Doe",
  streetAddress: "123 Main St",
  locality: "Berlin",
  postalCode: "10115",
  countryCode: "DE",
});
console.log(address.address.status); // "pending"

// List and inspect
const addresses = await zavu.addresses.list();
const one = await zavu.addresses.retrieve("addr_abc123");
await zavu.addresses.delete("addr_abc123");
上传合规文件

分为三个步骤:获取一次性上传 URL,将文件字节 POST 到该 URL,然后使用上传返回的 storageId 创建文件记录。API 本身不会检查文件格式或大小;控制台上传器接受不超过 10MB 的 JPEG、PNG 或 PDF 文件,因此请勿超出此限制。创建记录时,文件会在同一请求中转交给运营商审核:如果文件被拒绝,调用会返回 400,且不会保留记录。

创建的地址会返回 pending,创建的文件会返回 uploaded,API 之后不会将它们的状态更新为 verified 或 rejected。购买号码并不需要它们处于这些状态:审批状态由号码的 regulatoryStatus 跟踪,因此请轮询该字段。

// 1. Get upload URL (POST /v1/documents/upload-url)
const upload = await zavu.regulatoryDocuments.uploadURL();

// 2. POST the file to the presigned URL; the response carries the storageId
const uploaded = await fetch(upload.uploadUrl, {
  method: "POST",
  body: file, // a Blob or File
  headers: { "Content-Type": file.type },
});
const { storageId } = await uploaded.json();

// 3. Create document record (POST /v1/documents)
const doc = await zavu.regulatoryDocuments.create({
  name: "Passport Scan",
  documentType: "passport",
  storageId,
  mimeType: file.type,
  fileSize: file.size,
});
console.log(doc.document.status); // "uploaded"

// List, inspect, delete (verified documents cannot be deleted)
const docs = await zavu.regulatoryDocuments.list();
const detail = await zavu.regulatoryDocuments.retrieve("doc_xyz789");
await zavu.regulatoryDocuments.delete("doc_xyz789");
文件类型
类型描述
passport护照
national_id国家身份证
drivers_license驾驶证
utility_bill水电费账单
tax_id税务识别文件
business_registration企业注册文件
proof_of_address地址证明
other其他文件

10DLC(美国 A2P 消息)

若要大规模发送美国应用到个人消息,可能需要进行 10DLC 注册:

  1. 品牌注册 - 注册企业身份
  2. 营销活动注册 - 注册消息用途
  3. 号码分配 - 将已注册号码分配给营销活动

注册费用为 The Campaign Registry 收取的费用,从余额中扣除并按成本转收,分为两项独立费用:

费用一次性每月
品牌(POST /v1/10dlc/brands/{brandId}/submit)$4—
营销活动,标准用途(POST /v1/10dlc/campaigns/{campaignId}/submit)$15活跃期间 $10
营销活动,LOW_VOLUME 用途$2活跃期间 $2

一次性费用在提交时收取;如果运营商拒绝注册,或注册未能送达运营商,则会退款一次。每月营销活动费用按上述公示金额收取,自营销活动获批首日起开始计费。

状态会自动更新:每 30 分钟会从运营商重新读取待处理的营销活动,因此轮询 GET /v1/10dlc/campaigns/{campaignId} 即可。电话号码分配状态为 pending、active 或 failed(运营商拒绝了该号码;可以重新分配);移除的分配将不再列出。品牌的 ein 必须为 9 位数字(XX-XXXXXXX),且 website 必须是完整 URL,否则请求会被拒绝并返回 400。

10DLC 注册通过 Zavu 控制台管理。如有美国大批量消息需求,请联系支持团队。

限制

  • 购买电话号码需要付费套餐(Free 套餐会返回 402 paid_plan_required);付费套餐每个账户包含一个号码,仅限购买一次(Pro:美国号码)
  • 电话号码名称:最多 100 个字符
  • 释放号码前,必须先取消其与发送方的关联
  • 地址创建后状态为 pending,文件状态为 uploaded,并会一直保持不变;请轮询号码的 regulatoryStatus,而非这些状态
  • 国家代码:采用 2 位字母 ISO 格式(例如 US、DE、BR)
  • 搜索结果:每次请求最多 50 条
  • 有要求的号码需通过 type + regulatoryRequirements 购买,并且初始状态为 regulatoryStatus: "pending_review";在状态变为 approved 前,不能发送消息或拨打电话,获批后再将号码分配给发送方

评论

支持 Markdown