Skip to content

Email

Transactional email with templates, domain verification and delivery tracking.

1. Overview

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

2. Methods (17)

2.1email.send

POST /v1/email/send

Send a transactional email; supports templates and attachments.

Parameters

NameTypeRequiredDescription
tostring | string[]
Required
Recipient address or list of addresses.
subjectstring
Required
Subject line.
textstringOptionalPlain-text body.
htmlstringOptionalHTML body.
fromstringOptionalSender address (requires a verified domain).
ccstring[]OptionalCarbon-copy addresses.
bccstring[]OptionalBlind carbon-copy addresses.
template_idstringOptionalTemplate id to render instead of a body.
template_varsRecord<string, unknown>OptionalVariables passed to the template.
attachmentsArray<{ filename, content, mime? }>OptionalFiles to attach.
vendorstringOptionalPin a specific vendor instead of auto-routing.
idempotency_keystringOptionalOptional dedup key; identical retries return the same result.

Returns

EmailRecord { email_id, state, to, subject, vendor, created_at }
NameTypeDescription
message_idstringUnique identifier for this message
pattern: ^msg_[A-Za-z0-9]{20,}$
vendor_message_idstring | nullMessage identifier assigned by the upstream vendor
from_usedstringSender email address that was actually used for delivery
mode"default_vendor" | "verified_domain"Delivery mode or operation mode
scheduled_atstring | nullISO 8601 timestamp when the resource is scheduled to activate
format: date-time
accepted_recipientsstring[]List of recipient email addresses that were accepted
suppressed_recipientsstring[]List of recipient email addresses that were suppressed
metadataobject | nullCost/vendor disclosure for this send (cost-transparency contract surface). A superset of kernel ResultMetadata that also carries the email-specific `mode` field; present once a vendor route has been resolved (absent only if all recipients were pre-suppressed before delivery was attempted... still normally present with cost_usd=0 in that case).
metadata.request_idstringUUID v7.
metadata.trace_idstringDistributed tracing identifier
metadata.timestampstringUnix timestamp of the data point
format: date-time
metadata.latency_msintegerLatency of the operation in milliseconds
≥ 0
metadata.entry_formanyEntry point format (rest, mcp, sdk)
metadata.cost_usdnumberCost of this operation in USD
≥ 0
metadata.cost_cnynumberCost in CNY for this request
≥ 0
metadata.vendorstringAdapter name; references VendorRegistry.
metadata.vendor_region"china" | "western"Vendor region where the request was processed
metadata.markup_pctnumberMarkup percentage applied on top of vendor cost
metadata.mode"default_vendor" | "verified_domain"Email delivery mode this send resolved to (email-specific field not present on the generic kernel ResultMetadata).

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/email/send \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"to": "sample"}'

2.2email.get

GET /v1/email/get/{id}

Fetch a single email record by id.

Parameters

NameTypeRequiredDescription
idstring
Required
The email record id.

Returns

EmailRecord
NameTypeDescription
message_idstringArchive id of the message (msg_ + hex).
pattern: ^msg_[A-Za-z0-9]{12,}$
statestringAggregate state — see enums/email_state.yaml.
channel"email"Delivery channel of the archived record.
toanyRecipient(s) the message was sent to (string or array, as submitted).
vendorstringServing vendor that dispatched the message.
created_atnumber | stringEpoch seconds (or ISO-8601) when the message was archived.
per_recipient_stateobjectOPTIONAL — map of recipient_email -> per-recipient state (populated only when a delivery-event webhook pipeline is wired).
first_event_atstringOPTIONAL — first delivery-event timestamp (webhook-derived).
format: date-time
last_event_atstringOPTIONAL — latest delivery-event timestamp (webhook-derived).
format: date-time
countsobjectOPTIONAL — per-event-type tallies (delivered/bounced/opened/clicked/...), webhook-derived.

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/email/get/ID \
  -H "Authorization: Bearer $INFRAI_API_KEY"

2.3email.suppression.add

POST /v1/email/suppression/add

Add an address to the suppression list.

Returns

SuppressionRecord
NameTypeDescription
emailstringEmail address
format: email
reason"hard_bounce" | "soft_bounce_5x" | "complained" | "unsubscribed" | "invalid" | "manual" | "user_request"Reason for the current state or action
added_atstringISO 8601 timestamp when this resource was added
format: date-time
last_attempt_atstring | nullLast time a send was blocked by this entry.
format: date-time
attempt_count_blockedinteger | nullNumber of delivery attempts blocked by this suppression
≥ 0
notesstring | nullFree-text notes about this suppression
scope"account" | "domain"Scope of applicability for this resource
domain_scopestring | nullWhen scope=domain, the specific verified domain.

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/email/suppression/add \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email": "user@example.com"}'

2.4email.domain.verify

POST /v1/email/domain/verify

Verify a sending domain and return required DNS records.

Parameters

NameTypeRequiredDescription
domainstring
Required
The domain to verify.

Returns

{ verified, records: Array<{ type, name, value }> }
NameTypeDescription
domainstringApex domain, e.g. 'yourdomain.com'.
domain_idstringUnique identifier for this domain
pattern: ^dom_[A-Za-z0-9]{20,}$
status"pending_dns" | "verifying" | "verified" | "failed" | "expired"Current status of this resource
dns_recordsobject[]DNS records required for domain verification
dns_records[].type"TXT" | "CNAME" | "MX" | "A" | "AAAA"Type discriminator for this resource
dns_records[].namestringFully qualified DNS name.
dns_records[].valuestringValue of the DNS record or configuration
dns_records[].purpose"spf" | "dkim" | "tracking" | "dmarc" | "return_path" | "verification"Purpose of the DNS record
dns_records[].ttl_recommendedintegerRecommended TTL in seconds
≥ 60default: 3600
checksobject | nullPer-record check status ('ok'/'pending'/'mismatch'/...).
warm_up_state"not_started" | "in_progress" | "complete" | nullCurrent warm-up state for the domain
daily_limit_currentinteger | nullCurrent daily sending limit
≥ 0
daily_limit_targetinteger | nullTarget daily sending limit after warm-up
≥ 0
created_atstringISO 8601 timestamp when this resource was created
format: date-time
verified_atstring | nullISO 8601 timestamp when verification was completed
format: date-time
expires_atstring | nullDKIM rotation due (1y recommended).
format: date-time
rotatedbooleanPresent only on the response of email.domain.rotate_dkim: true once the DKIM key rotation has been issued (status drops back to pending_dns until the new record is observed in DNS).

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/email/domain/verify \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"domain": "sample"}'

2.5email.batch.send

POST /v1/email/batch/send

批量个性化发送,最多 100 条不同邮件共用一个 idempotency_key(批量直通,单条不重复计费)。

Parameters

NameTypeRequiredDescription
messagesEmailSendOptions[]
Required
邮件数组,每项是一个完整的 EmailSendRequest,各自带收件人与模板变量,1 到 100 条。
1–100 items
idempotency_keystringOptionalOptional dedup key; identical retries return the same result.

Returns

BatchSendResult { batch_id, results }
NameTypeDescription
batch_idstringUnique identifier for this batch job
pattern: ^batch_[A-Za-z0-9]{20,}$
resultsobject[]List of individual results from a batch operation
results[].indexintegerPosition of this message in the request messages[] array.
≥ 0
results[].message_idstring | nullNull when this message failed to enqueue.
pattern: ^msg_[A-Za-z0-9]{20,}$
results[].tostring | string[]-
results[].status"accepted" | "suppressed" | "failed"-
results[].errorstring | nullError code when status=failed (e.g. SUPPRESSED_RECIPIENT).

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/email/batch/send \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"messages": [{"to": "sample"}]}'

2.6email.event.list

GET /v1/email/event/list

List the event timeline for one email.

Parameters

NameTypeRequiredDescription
message_idstring
Required
Required. The message_id whose event timeline should be queried.
typestringOptional按事件类型过滤(如 delivered、bounced、opened)。
limitnumberOptionalMaximum items to return.
cursorstringOptionalPagination cursor.

Returns

{ items: EmailEvent[], next_cursor? }
NameTypeDescription
itemsobject[]List of resource records
items[].type"queued" | "sent" | "delivered" | "opened" | "clicked" | "bounced" | "complained" | "deferred" | "expired" | "cancelled" | "unsubscribed" | "auto_suppressed"Type discriminator for this resource
items[].atstringISO 8601 timestamp of the event
format: date-time
items[].recipientstringRecipient email address
format: email
items[].message_idstring | nullUnique identifier for this message
pattern: ^msg_[A-Za-z0-9]{20,}$
items[].metaobject | nullEvent-specific metadata (ip / user_agent / url / bounce_type / reason).
countintegerNumber of items in this page
≥ 0
next_cursorstring | nullPass back into event.list() to fetch the next 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/email/event/list \
  -H "Authorization: Bearer $INFRAI_API_KEY"

2.7email.suppression.check

GET /v1/email/suppression/check/{email}

查询某个收件地址是否在抑制名单中。

Parameters

NameTypeRequiredDescription
emailstring
Required
收件邮箱地址。

Returns

SuppressionCheckResult { is_suppressed, record? }
NameTypeDescription
emailstringThe email address that was checked.
suppressedbooleanWhether the address is currently suppressed
reason"hard_bounce" | "soft_bounce_5x" | "complained" | "unsubscribed" | "invalid" | "manual" | "user_request"Reason for the current suppression. Present only when suppressed=true.
added_atstringISO 8601 timestamp when this suppression was added. Present only when suppressed=true.
format: date-time
last_attempt_atstring | nullLast time a send was blocked by this entry. Present only when suppressed=true.
format: date-time
attempt_count_blockedinteger | nullNumber of delivery attempts blocked by this suppression. Present only when suppressed=true.
≥ 0
notesstring | nullFree-text notes about this suppression. Present only when suppressed=true.
scope"account" | "domain"Scope of applicability for this suppression entry. Present only when suppressed=true.
domain_scopestring | nullWhen scope=domain, the specific verified domain. Present only when suppressed=true.

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/email/suppression/check/EMAIL \
  -H "Authorization: Bearer $INFRAI_API_KEY"

2.8email.suppression.list

GET /v1/email/suppression/list

列出抑制名单中的收件地址。

Parameters

NameTypeRequiredDescription
reasonstringOptional按抑制原因过滤(如 bounce、complaint、manual)。
limitnumberOptionalMaximum items to return.
cursorstringOptionalPagination cursor.

Returns

{ items: SuppressionRecord[], next_cursor? }
NameTypeDescription
itemsobject[]List of resource records
items[].emailstringEmail address
format: email
items[].reason"hard_bounce" | "soft_bounce_5x" | "complained" | "unsubscribed" | "invalid" | "manual" | "user_request"Reason for the current state or action
items[].added_atstringISO 8601 timestamp when this resource was added
format: date-time
items[].last_attempt_atstring | nullLast time a send was blocked by this entry.
format: date-time
items[].attempt_count_blockedinteger | nullNumber of delivery attempts blocked by this suppression
≥ 0
items[].notesstring | nullFree-text notes about this suppression
items[].scope"account" | "domain"Scope of applicability for this resource
items[].domain_scopestring | nullWhen scope=domain, the specific verified domain.
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/email/suppression/list \
  -H "Authorization: Bearer $INFRAI_API_KEY"

2.9email.suppression.delete

DELETE /v1/email/suppression/delete/{email}

将某地址移出抑制名单,恢复对其投递。

Parameters

NameTypeRequiredDescription
emailstring
Required
收件邮箱地址。
idempotency_keystringOptionalOptional dedup key; identical retries return the same result.

Returns

{ deleted: boolean }
NameTypeDescription
emailstring | nullEmail address removed from suppression list
deletedbooleanWhether the suppression entry was removed (same value as `found`: the entry existed and was removed from the suppression store).
foundbooleanWhether a suppression entry existed for this email prior to the delete call.

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/email/suppression/delete/EMAIL \
  -H "Authorization: Bearer $INFRAI_API_KEY"

2.10email.domain.list

GET /v1/email/domain/list

列出账户下已添加的发信域名。

Parameters

NameTypeRequiredDescription
limitnumberOptionalMaximum items to return.
cursorstringOptionalPagination cursor.

Returns

{ items: DomainVerification[], next_cursor? }
NameTypeDescription
recordsobject[]List of resource records
records[].domainstringApex domain, e.g. 'yourdomain.com'.
records[].domain_idstringUnique identifier for this domain
pattern: ^dom_[A-Za-z0-9]{20,}$
records[].status"pending_dns" | "verifying" | "verified" | "failed" | "expired"Current status of this resource
records[].dns_recordsobject[]DNS records required for domain verification
records[].dns_records[].type"TXT" | "CNAME" | "MX" | "A" | "AAAA"Type discriminator for this resource
records[].dns_records[].namestringFully qualified DNS name.
records[].dns_records[].valuestringValue of the DNS record or configuration
records[].dns_records[].purpose"spf" | "dkim" | "tracking" | "dmarc" | "return_path" | "verification"Purpose of the DNS record
records[].dns_records[].ttl_recommendedintegerRecommended TTL in seconds
≥ 60default: 3600
records[].checksobject | nullPer-record check status ('ok'/'pending'/'mismatch'/...).
records[].warm_up_state"not_started" | "in_progress" | "complete" | nullCurrent warm-up state for the domain
records[].daily_limit_currentinteger | nullCurrent daily sending limit
≥ 0
records[].daily_limit_targetinteger | nullTarget daily sending limit after warm-up
≥ 0
records[].created_atstringISO 8601 timestamp when this resource was created
format: date-time
records[].verified_atstring | nullISO 8601 timestamp when verification was completed
format: date-time
records[].expires_atstring | nullDKIM rotation due (1y recommended).
format: date-time
records[].rotatedbooleanPresent only on the response of email.domain.rotate_dkim: true once the DKIM key rotation has been issued (status drops back to pending_dns until the new record is observed in DNS).
total_countintegerTotal number of items across all pages
≥ 0
next_cursorstring | nullPass back into domain.list() to fetch the next 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/email/domain/list \
  -H "Authorization: Bearer $INFRAI_API_KEY"

2.11email.domain.get

GET /v1/email/domain/get/{domain}

获取某个发信域名的验证状态与信誉信息。

Parameters

NameTypeRequiredDescription
domainstring
Required
The domain to verify.

Returns

DomainGetResult { verification, reputation }
NameTypeDescription
verificationobjectDomain verification status and DNS records
verification.domainstringApex domain, e.g. 'yourdomain.com'.
verification.domain_idstringUnique identifier for this domain
pattern: ^dom_[A-Za-z0-9]{20,}$
verification.status"pending_dns" | "verifying" | "verified" | "failed" | "expired"Current status of this resource
verification.dns_recordsobject[]DNS records required for domain verification
verification.dns_records[].type"TXT" | "CNAME" | "MX" | "A" | "AAAA"Type discriminator for this resource
verification.dns_records[].namestringFully qualified DNS name.
verification.dns_records[].valuestringValue of the DNS record or configuration
verification.dns_records[].purpose"spf" | "dkim" | "tracking" | "dmarc" | "return_path" | "verification"Purpose of the DNS record
verification.dns_records[].ttl_recommendedintegerRecommended TTL in seconds
≥ 60default: 3600
verification.checksobject | nullPer-record check status ('ok'/'pending'/'mismatch'/...).
verification.warm_up_state"not_started" | "in_progress" | "complete" | nullCurrent warm-up state for the domain
verification.daily_limit_currentinteger | nullCurrent daily sending limit
≥ 0
verification.daily_limit_targetinteger | nullTarget daily sending limit after warm-up
≥ 0
verification.created_atstringISO 8601 timestamp when this resource was created
format: date-time
verification.verified_atstring | nullISO 8601 timestamp when verification was completed
format: date-time
verification.expires_atstring | nullDKIM rotation due (1y recommended).
format: date-time
verification.rotatedbooleanPresent only on the response of email.domain.rotate_dkim: true once the DKIM key rotation has been issued (status drops back to pending_dns until the new record is observed in DNS).
reputationobject | nullNull until the domain is verified and has begun warming up.
reputation.domainstringDomain name
reputation.tier"warming_up" | "established" | "trusted" | "throttled" | "suspended"Current subscription tier (standard / pro / enterprise)
reputation.current_daily_capintegerCurrent daily sending cap
≥ 0
reputation.used_todayintegerNumber of emails sent today
≥ 0
reputation.bounce_rate_30dnumberBounce rate over the last 30 days
0–1
reputation.complaint_rate_30dnumberComplaint rate over the last 30 days
0–1
reputation.days_in_current_tierintegerDays in the current warm-up tier
≥ 0
reputation.next_tier"warming_up" | "established" | "trusted" | "throttled" | "suspended" | nullNext warm-up tier
reputation.next_tier_requirementsobject | nullConcrete thresholds + remaining-duration to upgrade.
reputation.throttle_risk"low" | "medium" | "high"Current risk of being throttled based on recent domain reputation metrics.

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/email/domain/get/DOMAIN \
  -H "Authorization: Bearer $INFRAI_API_KEY"

2.12email.domain.delete

DELETE /v1/email/domain/delete/{domain}

删除一个已添加的发信域名。

Parameters

NameTypeRequiredDescription
domainstring
Required
The domain to verify.
idempotency_keystringOptionalOptional dedup key; identical retries return the same result.

Returns

{ deleted: boolean }
NameTypeDescription
domainstring | nullDomain name that was deleted
deletedbooleanWhether the domain was deleted (same value as `found`: the domain existed and was removed from the self-managed sender-domain store).
foundbooleanWhether a domain verification record existed for this domain prior to the delete call.

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/email/domain/delete/DOMAIN \
  -H "Authorization: Bearer $INFRAI_API_KEY"

2.13email.domain.rotate_dkim

POST /v1/email/domain/rotate_dkim/{domain}

为发信域名轮换 DKIM 密钥,返回需配置的新 DNS 记录。

Parameters

NameTypeRequiredDescription
domainstring
Required
The domain to verify.
idempotency_keystringOptionalOptional dedup key; identical retries return the same result.

Returns

DomainVerification { domain, status, dns_records, ... }
NameTypeDescription
domainstringApex domain, e.g. 'yourdomain.com'.
domain_idstringUnique identifier for this domain
pattern: ^dom_[A-Za-z0-9]{20,}$
status"pending_dns" | "verifying" | "verified" | "failed" | "expired"Current status of this resource
dns_recordsobject[]DNS records required for domain verification
dns_records[].type"TXT" | "CNAME" | "MX" | "A" | "AAAA"Type discriminator for this resource
dns_records[].namestringFully qualified DNS name.
dns_records[].valuestringValue of the DNS record or configuration
dns_records[].purpose"spf" | "dkim" | "tracking" | "dmarc" | "return_path" | "verification"Purpose of the DNS record
dns_records[].ttl_recommendedintegerRecommended TTL in seconds
≥ 60default: 3600
checksobject | nullPer-record check status ('ok'/'pending'/'mismatch'/...).
warm_up_state"not_started" | "in_progress" | "complete" | nullCurrent warm-up state for the domain
daily_limit_currentinteger | nullCurrent daily sending limit
≥ 0
daily_limit_targetinteger | nullTarget daily sending limit after warm-up
≥ 0
created_atstringISO 8601 timestamp when this resource was created
format: date-time
verified_atstring | nullISO 8601 timestamp when verification was completed
format: date-time
expires_atstring | nullDKIM rotation due (1y recommended).
format: date-time
rotatedbooleanPresent only on the response of email.domain.rotate_dkim: true once the DKIM key rotation has been issued (status drops back to pending_dns until the new record is observed in DNS).

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/email/domain/rotate_dkim/DOMAIN \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

2.14email.template.create

POST /v1/email/template/create

创建一个邮件模板。

Parameters

NameTypeRequiredDescription
namestring
Required
模板名称,账户内唯一。
1–128 chars
subjectstring
Required
主题模板,可包含 {{var}} 占位符。
htmlstring
Required
HTML 正文模板,可包含 {{var}}、{{#section}}、{{^inverted}}。
body_textstringOptional纯文本备用正文。
variablesRecord<string, string>Optional声明的变量及类型,如 { name: 'string' }。
default_varsRecord<string, unknown>Optional发送时变量缺失所用的默认值。
tagsstring[]Optional模板标签列表。
idempotency_keystringOptionalOptional dedup key; identical retries return the same result.

Returns

Template { template_id, name, subject, html, ... }
NameTypeDescription
template_idstringIdentifier of the template used for rendering
pattern: ^tmpl_[A-Za-z0-9]{20,}$
namestringUnique within account.
1–128 chars
subjectstringMay contain double-brace placeholders (e.g. var).
htmlstringHTML body; may contain double-brace placeholders (var, #section, ^inverted).
body_textstring | nullPlain-text alternative.
variablesobject | nullDeclared variables: name with type 'string', 'int', 'bool', 'array', or 'object'.
default_varsobject | nullDefaults used when var missing in send().
tagsstring[] | nullTags for categorization and filtering
created_atstringISO 8601 timestamp when this resource was created
format: date-time
updated_atstringISO 8601 timestamp when this resource was last updated
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/email/template/create \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "example", "subject": "sample", "html": "<h1>Hello from infrai</h1>"}'

2.15email.template.update

PATCH /v1/email/template/update/{id}

更新一个已有的邮件模板。

Parameters

NameTypeRequiredDescription
idstring
Required
Template id to render instead of a body.
subjectstringOptional主题模板,可包含 {{var}} 占位符。
htmlstringOptionalHTML 正文模板,可包含 {{var}}、{{#section}}、{{^inverted}}。
body_textstringOptional纯文本备用正文。
variablesRecord<string, string>Optional声明的变量及类型,如 { name: 'string' }。
default_varsRecord<string, unknown>Optional发送时变量缺失所用的默认值。
tagsstring[]Optional模板标签列表。
idempotency_keystringOptionalOptional dedup key; identical retries return the same result.

Returns

Template { template_id, name, subject, html, ... }
NameTypeDescription
template_idstringIdentifier of the template used for rendering
pattern: ^tmpl_[A-Za-z0-9]{20,}$
namestringUnique within account.
1–128 chars
subjectstringMay contain double-brace placeholders (e.g. var).
htmlstringHTML body; may contain double-brace placeholders (var, #section, ^inverted).
body_textstring | nullPlain-text alternative.
variablesobject | nullDeclared variables: name with type 'string', 'int', 'bool', 'array', or 'object'.
default_varsobject | nullDefaults used when var missing in send().
tagsstring[] | nullTags for categorization and filtering
created_atstringISO 8601 timestamp when this resource was created
format: date-time
updated_atstringISO 8601 timestamp when this resource was last updated
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 PATCH https://api.infrai.cc/v1/email/template/update/ID \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

2.16email.template.delete

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

删除一个邮件模板。

Parameters

NameTypeRequiredDescription
idstring
Required
Template id to render instead of a body.
idempotency_keystringOptionalOptional dedup key; identical retries return the same result.

Returns

{ deleted: boolean }
NameTypeDescription
template_idstring | nullIdentifier of the deleted template
deletedbooleanWhether the template was deleted (same value as `found`: the template existed and was removed from the template store).
foundbooleanWhether a template existed with this id prior to the delete call.

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/email/template/delete/ID \
  -H "Authorization: Bearer $INFRAI_API_KEY"

2.17email.template.preview

POST /v1/email/template/preview/{id}

用给定变量渲染模板,预览主题、HTML、文本及缺失变量。

Parameters

NameTypeRequiredDescription
idstring
Required
Template id to render instead of a body.
varsRecord<string, unknown>
Required
用于渲染的变量值,会与模板的 default_vars 合并。

Returns

TemplatePreview { rendered_subject, rendered_html, rendered_text, missing_vars }
NameTypeDescription
rendered_subjectstringRendered subject line with variables substituted
rendered_htmlstringRendered HTML body with variables substituted
rendered_textstring | nullRendered plain text body with variables substituted
missing_varsstring[]Variables referenced by template but missing from input + default_vars.

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/email/template/preview/ID \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"vars": {}}'
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}

email.send

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.

email.batch.sendPOST /v1/email/batch/send

Send up to 100 personalized emails under one idempotency_key (batch passthrough, not billed per message).

Parameters (2)
NameTypeRequiredDescription
messagesobject[]RequiredEach entry is a full EmailSendRequest with its own recipients / template_vars.
1–100 items
idempotency_keystring | nullOptionalOne key for the whole batch; per-message sends are not re-charged.
email.domain.deleteDELETE /v1/email/domain/delete/{domain}

Delete a previously added sender domain.

Parameters (1)
NameTypeRequiredDescription
domainstringRequiredPath parameter.
email.domain.getGET /v1/email/domain/get/{domain}

Get the verification status and reputation of a sender domain.

Parameters (1)
NameTypeRequiredDescription
domainstringRequiredPath parameter.
email.domain.listGET /v1/email/domain/list

List the sender domains added to the account.

No request parameters.

email.domain.rotate_dkimPOST /v1/email/domain/rotate_dkim/{domain}

Rotate DKIM for a sender domain and return the new DNS records.

Parameters (2)
NameTypeRequiredDescription
domainstringRequiredPath parameter.
idempotency_keystring | nullOptionalClient-provided idempotency key; prevents duplicate execution on retry
email.domain.verifyPOST /v1/email/domain/verify

Verify a sender domain's DNS records to complete verification.

Parameters (2)
NameTypeRequiredDescription
domainstringRequiredSending domain to verify (e.g. mail.example.com).
idempotency_keystring | nullOptionalClient-provided idempotency key; prevents duplicate execution on retry
email.event.listGET /v1/email/event/list

List email delivery events (delivered, bounced, opened, clicked, complained).

No request parameters.

email.getGET /v1/email/get/{id}

Get the delivery details of one email by message_id.

Parameters (1)
NameTypeRequiredDescription
idstringRequiredPath parameter.
email.sendPOST /v1/email/send

Send a transactional email (inline body/HTML or a template) with tracking; idempotent.

Parameters (21)
NameTypeRequiredDescription
tostring | string[]RequiredRecipient address, or an array of addresses for multiple recipients.
ccstring[]OptionalCarbon copy recipients
bccstring[]OptionalBlind carbon copy recipients
fromstring | nullOptionalOptional. Omit to use Infrai's default sender on send.infrai.cc. If you provide a custom-domain sender, that domain must be verified first.
from_display_namestring | nullOptionalDisplay name for the sender
reply_tostring | nullOptionalReply-to email address
subjectstring | nullOptionalEmail subject line
bodystring | nullOptionalPlain text body.
htmlstring | nullOptionalHTML body of the email
template_idstring | nullOptionalIdentifier of the template used for rendering
template_varsobject | nullOptionalVariables to substitute in the template
attachmentsobject[]OptionalList of email attachments
headersobject | nullOptionalCustom HTTP headers to include in requests or responses
tagsstring[]OptionalTags for categorization and filtering
track_opensbooleanOptionalWhether to track email opens
default: false
track_clicksbooleanOptionalWhether to track link clicks in the email
default: false
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
vendorstring | nullOptionalPin to a specific vendor.
message_class"transactional" | "marketing"OptionalSemantic class of the message. Only transactional is currently live; marketing is reserved and fails closed.
default: "transactional"
auto_unsubscribe_linkboolean | nullOptionalWhether to append a signed unsubscribe link. Transactional messages omit it by default; marketing-like content may still be forced to include it.
email.suppression.addPOST /v1/email/suppression/add

Add a recipient address to the suppression list to stop future delivery; idempotent.

Parameters (6)
NameTypeRequiredDescription
emailstringRequiredEmail address
format: email
reason"hard_bounce" | "soft_bounce_5x" | "complained" | "unsubscribed" | "invalid" | "manual" | "user_request"OptionalReason for the current state or action
default: "manual"
scope"account" | "domain"OptionalScope of applicability for this resource
default: "account"
domain_scopestring | nullOptionalWhen scope=domain, the specific verified domain.
notesstring | nullOptionalFree-text notes about this suppression
idempotency_keystring | nullOptionalClient-provided idempotency key; prevents duplicate execution on retry
email.suppression.checkGET /v1/email/suppression/check/{email}

Check whether an address is on the suppression list.

Parameters (1)
NameTypeRequiredDescription
emailstringRequiredPath parameter.
email.suppression.deleteDELETE /v1/email/suppression/delete/{email}

Remove an address from the suppression list to resume delivery.

Parameters (1)
NameTypeRequiredDescription
emailstringRequiredPath parameter.
email.suppression.listGET /v1/email/suppression/list

List recipient addresses on the suppression list.

No request parameters.

email.template.createPOST /v1/email/template/create

Create an email template.

Parameters (8)
NameTypeRequiredDescription
namestringRequiredUnique within account.
1–128 chars
subjectstringRequiredMay contain double-brace var placeholders.
htmlstringRequiredHTML body; may contain double-brace var, double-brace #section, double-brace ^inverted.
body_textstring | nullOptionalPlain-text alternative.
variablesobject | nullOptionalDeclared variables: { name: 'string' | 'int' | 'bool' | 'array' | 'object' }.
default_varsobject | nullOptionalDefaults used when var missing in send().
tagsstring[] | nullOptionalTags for categorization and filtering
idempotency_keystring | nullOptionalClient-provided idempotency key; prevents duplicate execution on retry
email.template.deleteDELETE /v1/email/template/delete/{id}

Delete an email template.

Parameters (1)
NameTypeRequiredDescription
idstringRequiredPath parameter.
email.template.previewPOST /v1/email/template/preview/{id}

Render and preview a template with the given variables.

Parameters (2)
NameTypeRequiredDescription
idstringRequiredPath parameter.
varsobjectRequiredVariable values merged with the template's default_vars before rendering.
email.template.updatePATCH /v1/email/template/update/{id}

Update an existing email template.

Parameters (8)
NameTypeRequiredDescription
idstringRequiredPath parameter.
subjectstring | nullOptionalMay contain double-brace var placeholders.
htmlstring | nullOptionalHTML body; may contain double-brace var, double-brace #section, double-brace ^inverted.
body_textstring | nullOptionalPlain-text alternative.
variablesobject | nullOptionalTemplate variable definitions
default_varsobject | nullOptionalDefault variable values for the template
tagsstring[] | nullOptionalTags for categorization and filtering
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 · comm-email — 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) email.send — POST /v1/email/send · Send a transactional email (inline body/HTML or a template) with tracking; idempotent.
ask1 = input("Your email address (sends a real email): ").strip()
r1 = show("email.send", infrai("POST", "/v1/email/send", {"to":ask1,"subject":"Welcome","html":"<p>Hi!</p>"}))

# 2) email.get — GET /v1/email/get/{id} · Get the delivery details of one email by message_id.
id_2 = (r1.get("data") or {}).get("message_id") or ""
r2 = show("email.get", infrai("GET", f"/v1/email/get/{id_2}"))

# 3) email.event.list — GET /v1/email/event/list · List the delivery event timeline for one email; message_id is required.
r3 = show("email.event.list", infrai("GET", "/v1/email/event/list"))