Skip to content

SMS

SMS sending, OTP and verification, and delivery status.

1. Overview

Base path: https://api.infrai.cc/v1/sms
Auth header: Authorization: Bearer $INFRAI_API_KEY
bash
# Call any /v1/sms capability over raw HTTP — no SDK to install.
# curl:
curl https://api.infrai.cc/v1/sms/... \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json"

2. Methods (23)

2.1sms.send

POST /v1/sms/send

Send an SMS message; supports templates.

Parameters

NameTypeRequiredDescription
tostring
Required
Recipient phone number in E.164.
bodystringOptionalMessage text.
fromstringOptionalSender id or number.
template_idstringOptionalTemplate id to render instead of a body.
vendorstringOptionalPin a specific vendor instead of auto-routing.
idempotency_keystringOptionalOptional dedup key; identical retries return the same result.

Returns

SmsRecord { sms_id, to, state, vendor, segments, created_at }
NameTypeDescription
message_idstringUnique identifier for this message
pattern: ^sms_[A-Za-z0-9]{20,}$
state"queued" | "sending" | "sent" | "delivered" | "failed" | "deferred" | "expired" | "cancelled" | "auto_suppressed"Current lifecycle state of this resource
vendorstringVendor that handled or will handle this request
segmentsintegerLong SMS multi-part billing count.
≥ 1
cost_usdnumber | nullCost of this operation in USD
≥ 0
created_atstringISO 8601 timestamp when this resource was created
format: date-time

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X POST https://api.infrai.cc/v1/sms/send \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"to": "sample"}'

2.2sms.otp

POST /v1/sms/otp

Send a one-time passcode to a phone number.

Parameters

NameTypeRequiredDescription
tostring
Required
Recipient phone number in E.164.
e.g. +15555550100

Returns

{ request_id, expires_at }
NameTypeDescription
message_idstringUnique identifier for this message
pattern: ^sms_[A-Za-z0-9]{20,}$
state"queued" | "sending" | "sent" | "delivered" | "failed" | "deferred" | "expired" | "cancelled" | "auto_suppressed"Current lifecycle state of this resource
vendorstringVendor that handled or will handle this request
segmentsintegerLong SMS multi-part billing count.
≥ 1
cost_usdnumber | nullCost of this operation in USD
≥ 0
created_atstringISO 8601 timestamp when this resource was created
format: date-time

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X POST https://api.infrai.cc/v1/sms/otp \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"to": "+15555550100"}'

2.3sms.verify

POST /v1/sms/verify

Verify a one-time passcode.

Parameters

NameTypeRequiredDescription
tostring
Required
Recipient phone number in E.164.
codestring
Required
The one-time passcode to verify.

Returns

{ valid: boolean }
NameTypeDescription
verifiedbooleanWhether the verification succeeded
reason"verified" | "no_code_issued" | "expired" | "too_many_attempts" | "mismatch"Outcome reason: 'verified' on success; otherwise why verification failed
tostringPhone number that was checked

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X POST https://api.infrai.cc/v1/sms/verify \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"to": "sample", "code": "123456"}'

2.4sms.status

GET /v1/sms/status/{id}

Fetch the delivery status of an SMS.

Parameters

NameTypeRequiredDescription
idstring
Required
The SMS record id.

Returns

SmsRecord
NameTypeDescription
idstringMessage id (send returns e.g. 'sms_…'); the archive stores it under 'id'.
statusstringLifecycle state: one of enums/SmsState (queued|sending|sent|delivered|failed|deferred|expired|cancelled|auto_suppressed) or 'not_found' when the id is unknown.
channel"sms" | "email" | nullAlways 'sms' for this capability.
account_idstring | nullAccount identifier that owns this resource
toanyRecipient(s) as supplied at send time.
vendorstring | nullVendor that handled the send; null on a not-found read.
vendor_message_idstring | nullMessage identifier assigned by the upstream vendor
created_atstring | nullISO 8601 timestamp when this resource was created
format: date-time
foundbooleantrue when the id resolved to an archived message; false on a miss. (A miss should raise a typed 404 once SMS_MESSAGE_NOT_FOUND lands — see module notes.)
state"queued" | "sending" | "sent" | "delivered" | "failed" | "deferred" | "expired" | "cancelled" | "auto_suppressed"Current lifecycle state of this resource
attemptinteger | nullCurrent attempt number (for retries)
≥ 0
last_eventstring | nullDescription of the most recent event
delivered_atstring | nullISO 8601 timestamp when the message was delivered
format: date-time
failed_reasonstring | nullReason for failure, if the operation failed

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X GET https://api.infrai.cc/v1/sms/status/ID \
  -H "Authorization: Bearer $INFRAI_API_KEY"

2.5sms.batch.send

POST /v1/sms/batch/send

异构批量发送:每条为完整短信请求,整批共用一个幂等键,按条计费不重复。

Parameters

NameTypeRequiredDescription
messagesSmsSendRequest[]
Required
短信请求数组,最多 100 条,每条为完整的发送请求。
1–100 items
idempotency_keystringOptional整批共用的去重键;相同重试返回相同结果。

Returns

SmsBatchSendResult { results: SmsSendResult[] }
NameTypeDescription
resultsobject[]List of individual results from a batch operation
results[].indexintegerPosition in the request messages array.
≥ 0
results[].resultobject | nullSend result when this item succeeded.
results[].result.message_idstringUnique identifier for this message
pattern: ^sms_[A-Za-z0-9]{20,}$
results[].result.state"queued" | "sending" | "sent" | "delivered" | "failed" | "deferred" | "expired" | "cancelled" | "auto_suppressed"Current lifecycle state of this resource
results[].result.vendorstringVendor that handled or will handle this request
results[].result.segmentsintegerLong SMS multi-part billing count.
≥ 1
results[].result.cost_usdnumber | nullCost of this operation in USD
≥ 0
results[].result.created_atstringISO 8601 timestamp when this resource was created
format: date-time
results[].errorobject | nullError when this item failed; result is null.
results[].error.codestringStable identifier from registry.yaml.
results[].error.http_statusintegerHTTP status code of the webhook delivery attempt
400–599
results[].error.messagestringHuman-readable hint.
results[].error.docs_urlstringDocumentation URL for this error code
format: uri
results[].error.code_detailstringSub-classification (e.g. wallet cap reason).
results[].error.retryablebooleanWhether the error is retryable
results[].error.retry_after_msintegerSuggested retry delay in milliseconds
≥ 0
results[].error.paramstringWhich parameter failed validation, if applicable.
results[].error.trace_idstringDistributed tracing identifier
results[].error.request_idstringServer-assigned request identifier for tracing

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X POST https://api.infrai.cc/v1/sms/batch/send \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"messages": [{"to": "sample"}]}'

2.6sms.cancel

POST /v1/sms/cancel/{id}

取消尚未下发的已排程或排队中短信。

Parameters

NameTypeRequiredDescription
idstring
Required
要取消的短信消息 ID。

Returns

SmsCancelResult { message_id, cancelled, state }
NameTypeDescription
message_idstringUnique identifier for this message
pattern: ^sms_[A-Za-z0-9]{20,}$
cancelledbooleanWhether the resource was successfully cancelled
state"queued" | "sending" | "sent" | "delivered" | "failed" | "deferred" | "expired" | "cancelled" | "auto_suppressed"Current lifecycle state of this resource

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X POST https://api.infrai.cc/v1/sms/cancel/ID \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"message_id": "hello"}'

2.7sms.events

GET /v1/sms/events/{id}

读取单条短信的投递事件时间线。

Parameters

NameTypeRequiredDescription
idstring
Required
短信消息 ID。
cursorstringOptional分页游标,从上一页的 next_cursor 取得。
limitnumberOptional单页返回的最大条数。

Returns

SmsEventList { items: SmsEvent[], next_cursor }
NameTypeDescription
itemsobject[]Array of result items in this page
items[].type"queued" | "sending" | "sent" | "delivered" | "failed" | "deferred" | "expired" | "cancelled" | "auto_suppressed" | "delivery_receipt" | "inbound"Type discriminator for this resource
items[].atstringISO 8601 timestamp of the event
format: date-time
items[].recipientstringE.164 phone number.
items[].message_idstring | nullUnique identifier for this message
pattern: ^sms_[A-Za-z0-9]{20,}$
items[].metaobject | nullAdditional metadata for the event
next_cursorstring | nullOpaque cursor to fetch the next page; null/absent if this is the last page

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X GET https://api.infrai.cc/v1/sms/events/ID \
  -H "Authorization: Bearer $INFRAI_API_KEY"

2.8sms.inbound.list

GET /v1/sms/inbound/list

分页列出在已注册发送号上收到的入站(回复)短信。

Parameters

NameTypeRequiredDescription
cursorstringOptional分页游标,从上一页的 next_cursor 取得。
limitnumberOptional单页返回的最大条数。

Returns

SmsListResult { items, next_cursor }
NameTypeDescription
itemsobject[]Array of result items in this page
items[].type"queued" | "sending" | "sent" | "delivered" | "failed" | "deferred" | "expired" | "cancelled" | "auto_suppressed" | "delivery_receipt" | "inbound"Type discriminator for this resource
items[].atstringISO 8601 timestamp of the event
format: date-time
items[].recipientstringE.164 phone number.
items[].message_idstring | nullUnique identifier for this message
pattern: ^sms_[A-Za-z0-9]{20,}$
items[].metaobject | nullAdditional metadata for the event
next_cursorstring | nullOpaque cursor to fetch the next page; null/absent if this is the last page

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X GET https://api.infrai.cc/v1/sms/inbound/list \
  -H "Authorization: Bearer $INFRAI_API_KEY"

2.9sms.resend

POST /v1/sms/resend/{id}

重新下发短信,可选仅重试失败的收件人。

Parameters

NameTypeRequiredDescription
message_idstring
Required
要重发的原短信消息 ID。
pattern: ^sms_[A-Za-z0-9]{20,}$
only_failedbooleanOptional为 true 时仅重试投递失败的收件人。
default: true
idempotency_keystringOptional去重键;相同重试返回相同结果。

Returns

SmsBatchSendResult { results }
NameTypeDescription
message_idstringUnique identifier for this message
pattern: ^sms_[A-Za-z0-9]{20,}$
state"queued" | "sending" | "sent" | "delivered" | "failed" | "deferred" | "expired" | "cancelled" | "auto_suppressed"Current lifecycle state of this resource
vendorstringVendor that handled or will handle this request
segmentsintegerLong SMS multi-part billing count.
≥ 1
cost_usdnumber | nullCost of this operation in USD
≥ 0
created_atstringISO 8601 timestamp when this resource was created
format: date-time

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X POST https://api.infrai.cc/v1/sms/resend/ID \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"message_id": "hello"}'

2.10sms.sender.register

POST /v1/sms/sender/register

注册发送号码以供验证。

Parameters

NameTypeRequiredDescription
phone_numberstring
Required
要注册的发送号码(E.164 格式)。
regionstring
Required
发送号码所属区域,如 western、china。
methods("otp" | "voice" | "dns")[]Optional可用的验证方式列表。
idempotency_keystringOptional去重键;相同重试返回相同结果。

Returns

SenderVerification { sender_id, phone_number, region, state, methods, created_at }
NameTypeDescription
sender_idstringUnique identifier for this sender
phone_numberstringE.164.
regionstringISO-3166-1 alpha-2 (see SmsCountryCode).
state"pending" | "verified" | "failed"Current lifecycle state of this resource
methods("otp" | "voice" | "dns")[]Verification methods used for the sender
created_atstring | nullISO 8601 timestamp when this resource was created
format: date-time

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X POST https://api.infrai.cc/v1/sms/sender/register \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"phone_number": "+15555550100", "region": "sample"}'

2.11sms.sender.get

GET /v1/sms/sender/get/{id}

获取单个已注册发送号的详情。

Parameters

NameTypeRequiredDescription
idstring
Required
发送号 ID。

Returns

SenderVerification
NameTypeDescription
sender_idstringUnique identifier for this sender
phone_numberstringE.164.
regionstringISO-3166-1 alpha-2 (see SmsCountryCode).
state"pending" | "verified" | "failed"Current lifecycle state of this resource
methods("otp" | "voice" | "dns")[]Verification methods used for the sender
created_atstring | nullISO 8601 timestamp when this resource was created
format: date-time

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X GET https://api.infrai.cc/v1/sms/sender/get/ID \
  -H "Authorization: Bearer $INFRAI_API_KEY"

2.12sms.sender.list

GET /v1/sms/sender/list

分页列出已注册的发送号。

Parameters

NameTypeRequiredDescription
cursorstringOptional分页游标,从上一页的 next_cursor 取得。
limitnumberOptional单页返回的最大条数。

Returns

SmsSenderListResult { items, next_cursor }
NameTypeDescription
itemsobject[]Array of result items in this page
items[].sender_idstringUnique identifier for this sender
items[].phone_numberstringE.164.
items[].regionstringISO-3166-1 alpha-2 (see SmsCountryCode).
items[].state"pending" | "verified" | "failed"Current lifecycle state of this resource
items[].methods("otp" | "voice" | "dns")[]Verification methods used for the sender
items[].created_atstring | nullISO 8601 timestamp when this resource was created
format: date-time
countintegerNumber of items in this page
≥ 0
next_cursorstring | nullOpaque cursor to fetch the next page; null/absent if this is the last page

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X GET https://api.infrai.cc/v1/sms/sender/list \
  -H "Authorization: Bearer $INFRAI_API_KEY"

2.13sms.sender.delete

DELETE /v1/sms/sender/delete/{id}

删除一个已注册的发送号。

Parameters

NameTypeRequiredDescription
idstring
Required
要删除的发送号 ID。
idempotency_keystringOptional去重键;相同重试返回相同结果。

Returns

SmsDeleteResult { deleted }
NameTypeDescription
sender_idstring | nullIdentifier of the deleted sender
deletedbooleanWhether the sender was deleted
foundbooleanWhether a sender with this id existed

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X DELETE https://api.infrai.cc/v1/sms/sender/delete/ID \
  -H "Authorization: Bearer $INFRAI_API_KEY"

2.14sms.signature.create

POST /v1/sms/signature/create

创建短信签名(中国发送必需)并提交审核。

Parameters

NameTypeRequiredDescription
namestring
Required
签名内容文本。
type"company" | "app" | "website" | "public_account" | "store" | "other"Optional签名类型,如 enterprise、individual。
default: "company"
proof_urlstringOptional资质证明文件的 URL。
format: uri
remarkstringOptional提交审核时的备注说明。
vendorstringOptionalPin a specific vendor instead of auto-routing.

Returns

SmsSignature { signature_id, text, type, review_state, reject_reason, vendor, created_at }
NameTypeDescription
signature_idstringUnique identifier for this SMS signature
namestringSignature text shown as the 【签名】 prefix.
type"company" | "app" | "website" | "public_account" | "store" | "other"Signature scene (China vendor 签名来源).
default: "company"
review_state"pending" | "approved" | "rejected" | "n/a"China signatures always start 'pending' review; 'n/a' for non-China.
default: "pending"
review_reasonstring | nullVendor reviewer note when review_state=rejected.
proof_urlstring | nullURL of the ownership-proof document submitted to the China vendor.
vendor_sign_idstring | nullVendor-assigned sign id (Tencent SignId / Aliyun SignName) remembered after a real submit.
created_atstringISO 8601 timestamp when this resource was created
format: date-time
updated_atstring | nullISO 8601 timestamp when this resource was last updated
format: date-time
foundbooleanPresent on sms.signature.get; true when the signature exists. (A missing signature should raise a typed 404 once the SMS_SIGNATURE_NOT_FOUND code lands — see module notes.)

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X POST https://api.infrai.cc/v1/sms/signature/create \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "example"}'

2.15sms.signature.get

GET /v1/sms/signature/get/{id}

读取单个短信签名及其审核状态。

Parameters

NameTypeRequiredDescription
idstring
Required
签名 ID。

Returns

SmsSignature
NameTypeDescription
signature_idstringUnique identifier for this SMS signature
namestringSignature text shown as the 【签名】 prefix.
type"company" | "app" | "website" | "public_account" | "store" | "other"Signature scene (China vendor 签名来源).
default: "company"
review_state"pending" | "approved" | "rejected" | "n/a"China signatures always start 'pending' review; 'n/a' for non-China.
default: "pending"
review_reasonstring | nullVendor reviewer note when review_state=rejected.
proof_urlstring | nullURL of the ownership-proof document submitted to the China vendor.
vendor_sign_idstring | nullVendor-assigned sign id (Tencent SignId / Aliyun SignName) remembered after a real submit.
created_atstringISO 8601 timestamp when this resource was created
format: date-time
updated_atstring | nullISO 8601 timestamp when this resource was last updated
format: date-time
foundbooleanPresent on sms.signature.get; true when the signature exists. (A missing signature should raise a typed 404 once the SMS_SIGNATURE_NOT_FOUND code lands — see module notes.)

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X GET https://api.infrai.cc/v1/sms/signature/get/ID \
  -H "Authorization: Bearer $INFRAI_API_KEY"

2.16sms.signature.list

GET /v1/sms/signature/list

分页列出短信签名。

Parameters

NameTypeRequiredDescription
cursorstringOptional分页游标,从上一页的 next_cursor 取得。
limitnumberOptional单页返回的最大条数。

Returns

SmsSignatureListResult { items, next_cursor }
NameTypeDescription
itemsobject[]Array of result items in this page
items[].signature_idstringUnique identifier for this SMS signature
items[].namestringSignature text shown as the 【签名】 prefix.
items[].type"company" | "app" | "website" | "public_account" | "store" | "other"Signature scene (China vendor 签名来源).
default: "company"
items[].review_state"pending" | "approved" | "rejected" | "n/a"China signatures always start 'pending' review; 'n/a' for non-China.
default: "pending"
items[].review_reasonstring | nullVendor reviewer note when review_state=rejected.
items[].proof_urlstring | nullURL of the ownership-proof document submitted to the China vendor.
items[].vendor_sign_idstring | nullVendor-assigned sign id (Tencent SignId / Aliyun SignName) remembered after a real submit.
items[].created_atstringISO 8601 timestamp when this resource was created
format: date-time
items[].updated_atstring | nullISO 8601 timestamp when this resource was last updated
format: date-time
items[].foundbooleanPresent on sms.signature.get; true when the signature exists. (A missing signature should raise a typed 404 once the SMS_SIGNATURE_NOT_FOUND code lands — see module notes.)
next_cursorstring | nullOpaque cursor to fetch the next page; null/absent if this is the last page
countintegerTotal number of items across all pages
≥ 0

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X GET https://api.infrai.cc/v1/sms/signature/list \
  -H "Authorization: Bearer $INFRAI_API_KEY"

2.17sms.signature.delete

DELETE /v1/sms/signature/delete/{id}

删除一个短信签名。

Parameters

NameTypeRequiredDescription
idstring
Required
要删除的签名 ID。
idempotency_keystringOptional去重键;相同重试返回相同结果。

Returns

SmsDeleteResult { deleted }
NameTypeDescription
signature_idstring | nullIdentifier of the deleted signature
deletedbooleanWhether the signature was deleted
foundbooleanWhether a signature with this id existed

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X DELETE https://api.infrai.cc/v1/sms/signature/delete/ID \
  -H "Authorization: Bearer $INFRAI_API_KEY"

2.18sms.template.create

POST /v1/sms/template/create

创建带命名变量的可复用短信模板。

Parameters

NameTypeRequiredDescription
namestring
Required
模板名称。
bodystring
Required
模板正文,可含 {变量} 占位符。
localestringOptional模板语言区域,如 en、zh。
default: "en"
variablesstring[]Optional模板中使用的变量名列表。
vendorstringOptionalPin a specific vendor instead of auto-routing.

Returns

SmsTemplate { template_id, name, body, locale, variables, review_state, created_at }
NameTypeDescription
template_idstringIdentifier of the template used for rendering
namestringHuman-readable name for this resource
bodystringPlain text body of the message
localestringLocale code for the template (e.g. en-US, zh-CN)
default: "en"
variablesstring[]Template variable definitions
review_state"pending" | "approved" | "rejected" | "n/a"Required for China vendors; n/a otherwise.
default: "n/a"
review_reasonstring | nullVendor reviewer note when review_state=rejected.
vendor_template_idstring | nullVendor-assigned template id remembered after a real submit (polled by query_review_state).
created_atstringISO 8601 timestamp when this resource was created
format: date-time
updated_atstring | nullISO 8601 timestamp when this resource was last updated
format: date-time
foundbooleanPresent on sms.template.get; true when the template exists. (A missing template should raise a typed 404 once the SMS_TEMPLATE_NOT_FOUND code lands — see module notes.)

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X POST https://api.infrai.cc/v1/sms/template/create \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "example", "body": "hello"}'

2.19sms.template.delete

DELETE /v1/sms/template/delete/{id}

删除一个短信模板。

Parameters

NameTypeRequiredDescription
idstring
Required
要删除的模板 ID。
idempotency_keystringOptional去重键;相同重试返回相同结果。

Returns

SmsDeleteResult { deleted }
NameTypeDescription
template_idstring | nullIdentifier of the deleted template
deletedbooleanWhether the template was deleted
foundbooleanWhether a template with this id existed

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X DELETE https://api.infrai.cc/v1/sms/template/delete/ID \
  -H "Authorization: Bearer $INFRAI_API_KEY"

2.20sms.suppression.add

POST /v1/sms/suppression/add

将号码加入抑制(免打扰)列表。

Parameters

NameTypeRequiredDescription
phonestring
Required
要抑制的电话号码(E.164 格式)。
reason"user_request" | "stop_reply" | "carrier_block" | "invalid" | "manual"Optional抑制原因,如 opt_out、complaint。
default: "manual"
scope"account" | "sender"Optional抑制范围,如 account、global。
default: "account"
sender_scopestringOptional限定到某发送号的抑制范围。
notesstringOptional内部备注说明。
idempotency_keystringOptional去重键;相同重试返回相同结果。

Returns

SuppressionRecord { phone, scope, reason, created_at }
NameTypeDescription
phonestringE.164 phone.
reason"user_request" | "stop_reply" | "carrier_block" | "invalid" | "manual"Reason for the current state or action
added_atstringISO 8601 timestamp when this resource was added
format: date-time
scope"account" | "sender"Scope of applicability for this resource
sender_scopestring | nullWhen scope=sender, the sender_id.
last_attempt_atstring | nullISO 8601 timestamp of the most recent blocked send attempt, if any.
format: date-time
attempt_count_blockedintegerCount of send attempts blocked by this suppression entry so far.
≥ 0
notesstring | nullFree-form notes attached when the entry was added.

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X POST https://api.infrai.cc/v1/sms/suppression/add \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"phone": "+15555550100"}'

2.21sms.suppression.check

POST /v1/sms/suppression/check

发送前检查号码是否已被抑制。

Parameters

NameTypeRequiredDescription
phonestring
Required
要检查的电话号码(E.164 格式)。
scope"account" | "sender"Optional检查的抑制范围,如 account、global。
default: "account"
sender_scopestringOptional限定到某发送号的检查范围。

Returns

SmsSuppressionCheckResult { suppressed, record }
NameTypeDescription
phonestringE.164 phone that was checked.
suppressedbooleanWhether the address is currently suppressed
reason"user_request" | "stop_reply" | "carrier_block" | "invalid" | "manual"Suppression reason; present only when suppressed=true
added_atstringISO 8601 timestamp when the entry was added; present only when suppressed=true
format: date-time
scope"account" | "sender"Scope of the matching entry; present only when suppressed=true
sender_scopestring | nullWhen scope=sender, the sender_id; present only when suppressed=true
last_attempt_atstring | nullISO 8601 timestamp of the most recent blocked send attempt, if any
format: date-time
attempt_count_blockedintegerCount of send attempts blocked by this suppression entry so far; present only when suppressed=true
≥ 0
notesstring | nullFree-form notes attached when the entry was added

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X POST https://api.infrai.cc/v1/sms/suppression/check \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"phone": "+15555550100"}'

2.22sms.suppression.list

GET /v1/sms/suppression/list

分页列出被抑制的号码。

Parameters

NameTypeRequiredDescription
cursorstringOptional分页游标,从上一页的 next_cursor 取得。
limitnumberOptional单页返回的最大条数。

Returns

SmsSuppressionListResult { items, total_count, next_cursor }
NameTypeDescription
itemsobject[]Array of result items in this page
items[].phonestringE.164 phone.
items[].reason"user_request" | "stop_reply" | "carrier_block" | "invalid" | "manual"Reason for the current state or action
items[].added_atstringISO 8601 timestamp when this resource was added
format: date-time
items[].scope"account" | "sender"Scope of applicability for this resource
items[].sender_scopestring | nullWhen scope=sender, the sender_id.
items[].last_attempt_atstring | nullISO 8601 timestamp of the most recent blocked send attempt, if any.
format: date-time
items[].attempt_count_blockedintegerCount of send attempts blocked by this suppression entry so far.
≥ 0
items[].notesstring | nullFree-form notes attached when the entry was added.
countinteger | nullTotal number of items across all pages
≥ 0
total_countinteger | nullTotal number of items across all pages
≥ 0
next_cursorstring | nullOpaque cursor to fetch the next page; null/absent if this is the last page

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X GET https://api.infrai.cc/v1/sms/suppression/list \
  -H "Authorization: Bearer $INFRAI_API_KEY"

2.23sms.suppression.delete

POST /v1/sms/suppression/delete

从抑制列表移除号码以恢复发送。

Parameters

NameTypeRequiredDescription
phonestring
Required
要移除的电话号码(E.164 格式)。
scope"account" | "sender"Optional移除的抑制范围,如 account、global。
default: "account"
sender_scopestringOptional限定到某发送号的移除范围。
idempotency_keystringOptional去重键;相同重试返回相同结果。

Returns

SmsSuppressionRemoveResult { phone, removed }
NameTypeDescription
phonestringE.164 phone targeted.
deletedbooleanWhether the resource was successfully removed
foundbooleanWhether a matching entry existed

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X POST https://api.infrai.cc/v1/sms/suppression/delete \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"phone": "+15555550100"}'
Advanced: pin a vendor

By default infrai routes each call to the best available provider — you do not pick a vendor. As an escape hatch, this capability accepts an optional vendor parameter to pin one specific provider. Every live vendor for this capability is available in real time from the discovery endpoint for the capability id — see the discovery API.

GET /v1/discovery/{capability}

sms.send

sms.signature.create

sms.template.create

3. All capabilities

Every routed capability in this module — the complete public REST contract. The methods above are the guided walkthrough; this index is the full reference.

sms.batch.sendPOST /v1/sms/batch/send

Send a heterogeneous batch of SMS (each a full request) under one idempotency key, billed per message.

Parameters (2)
NameTypeRequiredDescription
messagesobject[]RequiredUp to 100 SmsSendRequest items.
1–100 items
idempotency_keystring | nullOptionalClient-provided idempotency key; prevents duplicate execution on retry
sms.cancelPOST /v1/sms/cancel/{id}

Cancel a scheduled or queued SMS that has not yet been dispatched.

Parameters (3)
NameTypeRequiredDescription
idstringRequiredPath parameter.
message_idstringRequiredId of the SMS message to cancel.
pattern: ^sms_[A-Za-z0-9]{20,}$
idempotency_keystring | nullOptionalClient-provided idempotency key; prevents duplicate execution on retry
sms.eventsGET /v1/sms/events/{id}

Retrieve the delivery event timeline for a single SMS message.

Parameters (1)
NameTypeRequiredDescription
idstringRequiredPath parameter.
sms.inbound.listGET /v1/sms/inbound/list

List inbound (reply) SMS received on registered sender numbers, with pagination.

No request parameters.

sms.otpPOST /v1/sms/otp

Send a one-time passcode via SMS with gateway-managed OTP lifecycle.

Parameters (4)
NameTypeRequiredDescription
tostringRequiredDestination phone number (E.164).
e.g. +15555550100
phonestring | nullOptionalLegacy alias for to.
templatestring | nullOptionalMessage template containing {code}; defaults to 'Your verification code is {code}'.
idempotency_keystring | nullOptionalClient-provided idempotency key; prevents duplicate execution on retry
sms.resendPOST /v1/sms/resend/{id}

Resend an SMS, optionally retrying only the failed recipients.

Parameters (4)
NameTypeRequiredDescription
idstringRequiredPath parameter.
message_idstringRequiredUnique identifier for this message
pattern: ^sms_[A-Za-z0-9]{20,}$
only_failedbooleanOptionalRe-dispatch only failed recipients; false resends the whole original recipient set.
default: true
idempotency_keystring | nullOptionalClient-provided idempotency key; prevents duplicate execution on retry
sms.sendPOST /v1/sms/send

Send an SMS message to one or more recipients (idempotent).

Parameters (12)
NameTypeRequiredDescription
tostring | string[]RequiredE.164 phone number or array of.
bodystring | nullOptionalPlain text body of the message
fromstring | nullOptionalSender ID / phone number; required for verified_sender mode.
template_idstring | nullOptionalIdentifier of the template used for rendering
template_varsobject | nullOptionalVariables to substitute in the template
vendorstring | nullOptionalPin to a specific vendor.
mode"default_vendor" | "verified_sender"OptionalDelivery mode or operation mode
default: "default_vendor"
scheduled_atstring | nullOptionalISO 8601 timestamp when the resource is scheduled to activate
format: date-time
idempotency_keystring | nullOptionalClient-provided idempotency key; prevents duplicate execution on retry
tagsstring[]OptionalTags for categorization and filtering
route_class"transactional" | "otp" | "marketing"OptionalSMS route class for delivery optimization
default: "transactional"
opt_in_proof_urlstring | nullOptionalRequired when route_class=marketing.
format: uri
sms.sender.deleteDELETE /v1/sms/sender/delete/{id}

Delete a registered sender number.

Parameters (1)
NameTypeRequiredDescription
idstringRequiredPath parameter.
sms.sender.getGET /v1/sms/sender/get/{id}

Retrieve details of a single registered sender number.

Parameters (1)
NameTypeRequiredDescription
idstringRequiredPath parameter.
sms.sender.listGET /v1/sms/sender/list

List registered sender numbers with pagination.

No request parameters.

sms.sender.registerPOST /v1/sms/sender/register

Register a sender number for verification.

Parameters (4)
NameTypeRequiredDescription
phone_numberstringRequiredE.164 phone number or alphanumeric sender ID.
regionstringRequiredISO-3166-1 alpha-2 (see SmsCountryCode).
methods("otp" | "voice" | "dns")[]OptionalVerification methods to attempt; vendor/region picks default if omitted.
idempotency_keystring | nullOptionalClient-provided idempotency key; prevents duplicate execution on retry
sms.signature.createPOST /v1/sms/signature/create

Create an SMS signature (required for China delivery) and submit it for review.

Parameters (5)
NameTypeRequiredDescription
namestringRequiredSignature text shown as the 【签名】 prefix, e.g. 'Acme'.
type"company" | "app" | "website" | "public_account" | "store" | "other"OptionalSignature scene (China vendor 签名来源).
default: "company"
proof_urlstring | nullOptionalURL to the authorization letter / business-license image required for brand review.
format: uri
remarkstring | nullOptionalNote shown to the vendor reviewer.
vendorstring | nullOptionalPin the vendor to register at; otherwise the gateway picks per region.
sms.signature.deleteDELETE /v1/sms/signature/delete/{id}

Delete a registered SMS signature (China-route vendor pre-config); sends referencing it will be rejected.

Parameters (1)
NameTypeRequiredDescription
idstringRequiredPath parameter.
sms.signature.getGET /v1/sms/signature/get/{id}

Retrieve a single SMS signature and its review status.

Parameters (1)
NameTypeRequiredDescription
idstringRequiredPath parameter.
sms.signature.listGET /v1/sms/signature/list

List SMS signatures with pagination.

No request parameters.

sms.statusGET /v1/sms/status/{id}

Query the delivery status of an SMS message by ID.

Parameters (1)
NameTypeRequiredDescription
idstringRequiredPath parameter.
sms.suppression.addPOST /v1/sms/suppression/add

Add a phone number to the suppression (do-not-contact) list.

Parameters (6)
NameTypeRequiredDescription
phonestringRequiredE.164 phone.
reason"user_request" | "stop_reply" | "carrier_block" | "invalid" | "manual"OptionalReason for the current state or action
default: "manual"
scope"account" | "sender"OptionalScope of applicability for this resource
default: "account"
sender_scopestring | nullOptionalRequired when scope=sender: the sender_id the suppression is bound to.
notesstring | nullOptionalFree-text notes about this suppression
idempotency_keystring | nullOptionalClient-provided idempotency key; prevents duplicate execution on retry
sms.suppression.checkPOST /v1/sms/suppression/check

Check whether a phone number is suppressed before sending.

Parameters (3)
NameTypeRequiredDescription
phonestringRequiredE.164 phone.
scope"account" | "sender"OptionalScope of applicability for this resource
default: "account"
sender_scopestring | nullOptionalRequired when scope=sender.
sms.suppression.deletePOST /v1/sms/suppression/delete

Remove a number from the suppression list to resume sending.

Parameters (4)
NameTypeRequiredDescription
phonestringRequiredE.164 phone.
scope"account" | "sender"OptionalScope of applicability for this resource
default: "account"
sender_scopestring | nullOptionalRequired when scope=sender.
idempotency_keystring | nullOptionalClient-provided idempotency key; prevents duplicate execution on retry
sms.suppression.listGET /v1/sms/suppression/list

List suppressed phone numbers with pagination.

No request parameters.

sms.template.createPOST /v1/sms/template/create

Create a reusable SMS template with named variables.

Parameters (5)
NameTypeRequiredDescription
namestringRequiredHuman label for the template.
bodystringRequiredTemplate text with double-brace var placeholders (Mustache-subset).
localestringOptionalzh/cn locales trigger China-vendor review.
default: "en"
variablesstring[]OptionalDeclared placeholder names; inferred from body if omitted.
vendorstring | nullOptionalPin the vendor to register at; otherwise the gateway picks per region.
sms.template.deleteDELETE /v1/sms/template/delete/{id}

Delete a registered SMS message template (vendor pre-config); sends referencing it will be rejected.

Parameters (1)
NameTypeRequiredDescription
idstringRequiredPath parameter.
sms.verifyPOST /v1/sms/verify

Verify a user-submitted SMS one-time passcode.

Parameters (5)
NameTypeRequiredDescription
tostringRequiredPhone number the OTP was issued to (E.164).
phonestring | nullOptionalLegacy alias for to.
codestringRequiredThe one-time code to verify.
otpstring | nullOptionalLegacy alias for code.
idempotency_keystring | nullOptionalClient-provided idempotency key; prevents duplicate execution on retry

4. End-to-end example

A production-style walkthrough of this module: configure once, then run the flow. It exercises most of the module's APIs.

A copy-paste-runnable single-file Python program (stdlib only, no SDK): set your INFRAI_API_KEY, run it, and walk this module's core flow with REAL billed calls — later steps reuse real fields returned by earlier ones. The 12-line helper is the entire integration.

python
#!/usr/bin/env python3
"""Infrai · sms — runnable real-app example (single file, zero deps).

Copy this file, set your key, run it: every step is a REAL call to
api.infrai.cc, billed at the real (tiny) per-call price, printing the
live JSON response. Get a key at https://infrai.cc/login (Google/
GitHub sign-in grants $2 free credit); add funds at
https://infrai.cc/billing. No SDK — the 12-line helper below is the
entire integration."""
import json
import os
from urllib import error, request

KEY = os.environ.get("INFRAI_API_KEY") or "ifr_..."  # <- your key
BASE = "https://api.infrai.cc"


# Same raw HTTPS POST/GET as every per-method example on this page —
# wrapped once for reuse. There is nothing else to it: no SDK.
def infrai(method, path, body=None):
    req = request.Request(
        BASE + path, method=method,
        data=json.dumps(body).encode() if body is not None else None,
        headers={"Authorization": f"Bearer {KEY}",
                 "Content-Type": "application/json"})
    try:
        with request.urlopen(req, timeout=60) as r:
            return json.loads(r.read())
    except error.HTTPError as e:
        return json.loads(e.read())


def show(label, resp):
    print(f"\n== {label} ==")
    print(json.dumps(resp, indent=2, ensure_ascii=False))
    return resp


# 1) sms.otp — POST /v1/sms/otp · Send a one-time passcode via SMS with gateway-managed OTP lifecycle.
ask1 = input("Your phone number, intl format (+86...): ").strip()
r1 = show("sms.otp", infrai("POST", "/v1/sms/otp", {"to":ask1}))

# 2) sms.verify — POST /v1/sms/verify · Verify a user-submitted SMS one-time passcode.
ask2 = input("Enter the code you just received: ").strip()
r2 = show("sms.verify", infrai("POST", "/v1/sms/verify", {"to":ask1,"code":ask2}))