关于 phone-numbers
phone-numbers 是通过 Zavu API 搜索、购买和管理电话号码的技能,面向需要处理号码类型、运营商监管要求和 Sender 分配的开发者。
主要功能
- 01按国家和类型搜索号码
- 02购买和管理号码
- 03查询运营商要求
- 04提交地址和文件
- 05将号码分配给 Sender
适用场景
- 01查找符合地区或号码模式的号码
- 02提交合规资料并购买号码
- 03跟踪号码监管审批
- 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 完成:
GET /v1/phone-numbers/requirements?phoneNumber=%2B4930123456&type=local(将+编码为%2B;不编码的+也可以)。响应会列出购买该号码时需要验证的信息;如果无法解析该号码自身的要求,则返回其国家和type对应的列表。items为空表示该号码无需提供信息,可直接购买。502 requirements_unavailable表示查询失败:请重试,切勿将其视为“无需提供信息”(即使发生这种情况,美国和加拿大号码也会作为无需提供信息的号码出售)。- 对于每个
requirementTypes[]条目:address→ 在同一项目中通过POST /v1/addresses创建一个地址(必须提供firstName和lastName),并使用其id;document→ 上传一个文件(POST /v1/documents,见下文),并使用其id;textual→ 使用文本本身;action→ 无需为其发送任何内容。每个id只提交一次。 - 购买时提供
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>" }
]
}'
- 号码会立即购买并计费,其
regulatoryStatus为"pending_review"。在regulatoryStatus变为"approved"之前,该号码无法发送消息或拨打电话。系统每 6 小时重新检查一次状态:轮询GET /v1/phone-numbers/{phoneNumberId}。 - 将号码分配给发送方(通过
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 注册:
- 品牌注册 - 注册企业身份
- 营销活动注册 - 注册消息用途
- 号码分配 - 将已注册号码分配给营销活动
注册费用为 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前,不能发送消息或拨打电话,获批后再将号码分配给发送方