team-telnyx/ai/skills/telnyx-email-domains-curl/SKILL.md
telnyx-email-domains-curl
Manage email sending domains, verify DNS records (SPF, DKIM, DMARC, MX), check domain health, and configure domain-level webhooks for delivery events.
- Source repository stars
- 201
- Declared platforms
- 0
- Static risk flags
- 2
- Last source update
- 2026-08-04
- Source checked
- 2026-08-04
Decision brief
What it does—and where it fits
Manage email sending domains, verify DNS records (SPF, DKIM, DMARC, MX), check domain health, and configure domain-level webhooks for delivery events.
Not for
- Tasks that require unconfirmed production actions or broad system permissions.
- Environments where the pinned source and install steps cannot be inspected.
Compatibility matrix
Platform support, with evidence labels
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
Inspect first. Install second.
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/team-telnyx/ai --skill "skills/telnyx-email-domains-curl"Inspect the Agent Skill "telnyx-email-domains-curl" from https://github.com/team-telnyx/ai/blob/50f446de5b77867ff751d1a2e65e4c54ba692278/skills/telnyx-email-domains-curl/SKILL.md at commit 50f446de5b77867ff751d1a2e65e4c54ba692278. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
What the source asks the agent to do
- 01
Setup
bash export TELNYXAPIKEY="YOURAPIKEYHERE" export TELNYXAPIBASE="https://api.telnyx.com/v2"
bash export TELNYXAPIKEY="YOURAPIKEYHERE" export TELNYXAPIBASE="https://api.telnyx.com/v2" - 02
3. Trigger DNS verification
POST /v2/emaildomains/{domainid}/verify
POST /v2/emaildomains/{domainid}/verifyExpected status: 200. Inspect .data.verification and each .data.dnsrecords[].status. A 200 means the check ran; it does not guarantee that every record verified. - 03
Verify and process webhook deliveries
Telnyx signs webhook deliveries with Ed25519 and sends the telnyx-signature-ed25519 and telnyx-timestamp headers. Follow this order for every delivery:
Read and retain the request's raw body bytes. Do not parse JSON first; changingRead telnyx-timestamp and reject requests outside a 5-minute timestampVerify telnyx-signature-ed25519 against the timestamp and raw body with your - 04
Installation
Review the “Installation” section in the pinned source before continuing.
Review and apply the “Installation” source section. - 05
curl is pre-installed on macOS, Linux, and Windows 10+.
Review the “curl is pre-installed on macOS, Linux, and Windows 10+.” section in the pinned source before continuing.
Review and apply the “curl is pre-installed on macOS, Linux, and Windows 10+.” source section.
Permission review
Static risk signals and limitations
Network access
The documentation includes network, browsing, or remote request actions.
# curl is pre-installed on macOS, Linux, and Windows 10+.Network access
The documentation includes network, browsing, or remote request actions.
export TELNYX_API_BASE="https://api.telnyx.com/v2"Sends data out
The documentation includes sending, uploading, or posting data to a remote service.
Expected status: `200` with the deleted webhook in `.data`, not `204`.Sends data out
The documentation includes sending, uploading, or posting data to a remote service.
| 10 | Create a domain webhook | `createEmailDomainWebhook` | `POST /v2/email_domains/{domain_id}/webhooks` | `domain_id`, `url`, `events` |Evidence record
Why each signal appears
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 91/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 201 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
Provenance and original SKILL.md
- Repository
- team-telnyx/ai
- Skill path
- skills/telnyx-email-domains-curl/SKILL.md
- Commit
- 50f446de5b77867ff751d1a2e65e4c54ba692278
- License
- MIT
- Collected
- 2026-08-04
- Default branch
- main
View the original SKILL.md
Telnyx Email Domains — curl
Installation
# curl is pre-installed on macOS, Linux, and Windows 10+.
# A JSON formatter such as `python3 -m json.tool` is optional.
Setup
export TELNYX_API_KEY="YOUR_API_KEY_HERE"
export TELNYX_API_BASE="https://api.telnyx.com/v2"
# Set these from API responses after creating or listing resources.
export EMAIL_DOMAIN_ID="123e4567-e89b-12d3-a456-426614174000"
export EMAIL_WEBHOOK_ID="123e4567-e89b-12d3-a456-426614174003"
Every request requires:
-H "Authorization: Bearer $TELNYX_API_KEY"
Mutation requests with JSON also require:
-H "Content-Type: application/json"
Use --fail-with-body --silent --show-error in automation so non-2xx responses
fail the command without hiding the Telnyx error body.
Error Handling
Error responses use an errors array:
{
"errors": [
{
"code": "10015",
"title": "Validation Failed",
"detail": "domain is invalid",
"source": {"pointer": "/data/attributes/domain"}
}
]
}
Common cases:
| HTTP | Meaning | Action |
|---|---|---|
400 | Invalid list query or malformed input | Fix the query; do not retry unchanged. |
401 | Missing or invalid API key | Fix authentication. |
403 | Shared domain is read-only (10008) or access is insufficient | Use an owned custom domain or correct permissions. |
404 | Domain or webhook not found (10001) | Re-list resources and verify both IDs. |
422 | Request validation or state transition failed (10015 and related codes) | Inspect every error and source.pointer; correct the request or state. |
429 | Rate limit | Honor Retry-After when present and back off. |
500 | Unexpected service error | Retry only safe reads or carefully reconciled mutations. |
Do not retry a create blindly after a transport timeout; first list domains and
check whether the resource was created. verify and GET operations are safe to
repeat. Before retrying DELETE or PATCH, retrieve the current state. Use bounded
exponential backoff with jitter for transient 429 and 5xx failures.
Important Notes
- All 13 reachable operations use the Telnyx v2 REST API and Bearer authentication.
- A custom domain is not ready merely because
POST /v2/email_domainssucceeds. Create it, retrieve its generated DNS records, publish those records, trigger verification, and check health untilusable_for_sendingistrue. - Call
GET /v2/email_domains/{domain_id}/dns_recordsto retrieve the exact DNS records you need to publish. The response includes the record type, host, value, and priority for each record. - The OpenAPI DNS-purpose enum includes
ownership,spf,dkim,dmarc, andmx. SPF, DKIM, and DMARC are authentication-related purposes; MX supports inbound routing when required. Publish the exact API-returned values rather than constructing DNS records from examples. - Webhooks are configured at the domain level through
POST /v2/email_domains/{domain_id}/webhooks, not per message. - Domain IDs and webhook IDs are UUIDs returned by the API, not domain names.
Operational Caveats
- Shared versus custom domains: Telnyx-managed shared domains are
pre-provisioned and readable/usable by accounts. Custom domains require
customer DNS setup and verification. Non-owners cannot update, verify, or
delete a shared domain; those attempts return
403with code10008. - DNS is API-generated: The API does not expose customer-facing create/update/delete operations for individual generated DNS records. Publish records at the authoritative DNS provider, then call the verify operation.
- Tracking defaults live on the domain:
open_tracking,click_tracking, andunsubscribe_trackingdefault tofalse,false, andtrue, respectively. A send may override these defaults without changing the domain. - Health is the readiness signal: Do not infer deliverability from one DNS record. Check the aggregate health response and the relevant usability boolean.
- Verification reflects DNS propagation: A successful verify request means the check ran, not that every record passed. Wait and use bounded backoff before checking again; never tight-loop verification.
- Verified deletion requires intent: Pass
force=trueto delete a verified custom domain. Delete returns200with the deleted domain, not204. - Pagination differs by resource: Domain lists support offset or cursor
pagination. Webhook lists support offset pagination only. Treat cursors as
opaque and inspect the returned
.metashape.
Reference Use Rules
Do not invent request fields, DNS values, event names, response fields, or status enums.
- Read references/api-details.md for complete request/response schemas and every enum.
- Before constructing list filters or pagination, read List query parameters.
- Before branching on DNS or health, read DNS and verification semantics and Response schemas.
- Before subscribing to events, read Webhook event allowlist. The allowlist is explicit and has no default-to-all behavior.
- Before retrying failures, read Errors and retry behavior.
Core Tasks
Provision and verify a custom domain
1. Create a domain
POST /v2/email_domains
| Parameter | Type | Required | Description |
|---|---|---|---|
domain | string | Yes | Custom domain name, for example example.com. |
inbound_enabled | boolean | No | Enable inbound routing; defaults to false. |
dmarc_policy | object | null | No | Advisory DMARC policy (p, pct, rua, sp). |
tracking | object | No | Domain defaults for open, click, and unsubscribe tracking. |
curl --fail-with-body --silent --show-error \
-X POST \
-H "Authorization: Bearer $TELNYX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"domain": "example.com",
"inbound_enabled": true,
"dmarc_policy": {
"p": "none",
"pct": 100,
"rua": "mailto:[email protected]"
},
"tracking": {
"open_tracking": true,
"click_tracking": true,
"unsubscribe_tracking": true
}
}' \
"$TELNYX_API_BASE/email_domains"
Expected status: 201. Save .data.id as EMAIL_DOMAIN_ID. Do not send until
.data.usable_for_sending is true.
2. Retrieve the required DNS records
GET /v2/email_domains/{domain_id}/dns_records
| Parameter | Type | Required | Description |
|---|---|---|---|
domain_id | UUID path parameter | Yes | Domain ID returned by the API. |
curl --fail-with-body --silent --show-error \
-H "Authorization: Bearer $TELNYX_API_KEY" \
"$TELNYX_API_BASE/email_domains/$EMAIL_DOMAIN_ID/dns_records"
Each item in .data[] includes purpose, record_type, host, value,
priority, required, status, and possibly actual_value. Publish every
required record exactly as returned. Use the response to decide which records
are required for this domain's sending and inbound configuration.
3. Trigger DNS verification
POST /v2/email_domains/{domain_id}/verify
| Parameter | Type | Required | Description |
|---|---|---|---|
domain_id | UUID path parameter | Yes | Domain whose current DNS records should be checked. |
| Request body | — | No | This operation has no request body. |
curl --fail-with-body --silent --show-error \
-X POST \
-H "Authorization: Bearer $TELNYX_API_KEY" \
"$TELNYX_API_BASE/email_domains/$EMAIL_DOMAIN_ID/verify"
Expected status: 200. Inspect .data.verification and each
.data.dns_records[].status. A 200 means the check ran; it does not guarantee
that every record verified.
4. Check domain health
GET /v2/email_domains/{id}/health
| Parameter | Type | Required | Description |
|---|---|---|---|
id | UUID path parameter | Yes | Domain whose aggregate readiness should be checked. |
curl --fail-with-body --silent --show-error \
-H "Authorization: Bearer $TELNYX_API_KEY" \
"$TELNYX_API_BASE/email_domains/$EMAIL_DOMAIN_ID/health"
Read .data.status, .data.usable_for_sending, .data.usable_for_inbound,
.data.verification, and .data.checked_at. DMARC may be missing_optional
without blocking sending; use each record's required flag and the health
booleans rather than treating every non-verified value as fatal.
List domains
GET /v2/email_domains
| Query parameter | Type | Required | Description |
|---|---|---|---|
page[number] | integer | No | Offset page number. |
page[size] | integer | No | Page size from 1 to 100. |
sort | enum | No | created_at, -created_at, domain, or -domain. |
filter[type] | enum | No | custom, shared, or shared_inbound. |
filter[usable_for_sending] | boolean | No | Limit results by sending readiness. |
| ... | See all list query parameters. |
curl --fail-with-body --silent --show-error --get \
-H "Authorization: Bearer $TELNYX_API_KEY" \
--data-urlencode "page[number]=1" \
--data-urlencode "page[size]=25" \
--data-urlencode "sort=-created_at" \
--data-urlencode "filter[type]=custom" \
--data-urlencode "filter[usable_for_sending]=true" \
"$TELNYX_API_BASE/email_domains"
Supported filters also include status, partial case-insensitive domain,
profile_id, and usable_for_inbound. Domain lists support offset pagination
and cursor pagination; inspect the returned .meta shape.
Retrieve a domain
GET /v2/email_domains/{id}
| Parameter | Type | Required | Description |
|---|---|---|---|
id | UUID path parameter | Yes | Domain to retrieve. |
curl --fail-with-body --silent --show-error \
-H "Authorization: Bearer $TELNYX_API_KEY" \
"$TELNYX_API_BASE/email_domains/$EMAIL_DOMAIN_ID"
Expected status: 200. The response includes DNS, DKIM, inbound, DMARC,
tracking, usability, timestamps, and optional reputation information.
Update a domain
PATCH /v2/email_domains/{id}
| Parameter | Type | Required | Description |
|---|---|---|---|
id | UUID path parameter | Yes | Domain to update. |
inbound_enabled | boolean | No | Enable or disable inbound routing. |
dmarc_policy | object | null | No | Change the advisory DMARC policy. |
tracking | object | No | Change domain tracking defaults. |
The domain name and type are not mutable. Include at least one field to change.
Updating the DMARC policy rebuilds the recommended DMARC record and resets its
verification to pending, so retrieve the new DNS records, publish the returned
value, and verify again.
curl --fail-with-body --silent --show-error \
-X PATCH \
-H "Authorization: Bearer $TELNYX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"inbound_enabled": true,
"tracking": {
"open_tracking": false,
"click_tracking": true,
"unsubscribe_tracking": true
}
}' \
"$TELNYX_API_BASE/email_domains/$EMAIL_DOMAIN_ID"
Expected status: 200. A non-owner cannot mutate a shared domain (403, code
10008).
Delete a domain
DELETE /v2/email_domains/{id}
| Parameter | Type | Required | Description |
|---|---|---|---|
id | UUID path parameter | Yes | Domain to delete. |
force | boolean query parameter | For verified domains | Must be true to delete a verified domain. |
# For a pending or unverified custom domain:
curl --fail-with-body --silent --show-error \
-X DELETE \
-H "Authorization: Bearer $TELNYX_API_KEY" \
"$TELNYX_API_BASE/email_domains/$EMAIL_DOMAIN_ID"
# For a verified custom domain, explicitly confirm deletion:
curl --fail-with-body --silent --show-error --get \
-X DELETE \
-H "Authorization: Bearer $TELNYX_API_KEY" \
--data-urlencode "force=true" \
"$TELNYX_API_BASE/email_domains/$EMAIL_DOMAIN_ID"
Expected status: 200 with the deleted domain in .data. A non-owner cannot
delete a shared domain.
Webhooks
Webhooks are configured at the domain level through
POST /v2/email_domains/{domain_id}/webhooks, not per message. A subscription
contains a delivery URL and a non-empty explicit event allowlist.
Verify and process webhook deliveries
Telnyx signs webhook deliveries with Ed25519 and sends the
telnyx-signature-ed25519 and telnyx-timestamp headers. Follow this order for
every delivery:
- Read and retain the request's raw body bytes. Do not parse JSON first; changing whitespace or serialization before verification invalidates the signed body.
- Read
telnyx-timestampand reject requests outside a 5-minute timestamp tolerance to limit replay attacks. - Verify
telnyx-signature-ed25519against the timestamp and raw body with your Telnyx Ed25519 public key. Use the official Telnyx verifier for your runtime where available. Reject the request before parsing or processing if signature verification fails. - Parse the verified body, extract its event ID, and atomically record that ID. If the event ID was already processed, return a success response without repeating side effects.
- Persist or enqueue work, then return a
2xxresponse within 10 seconds. Keep slow downstream processing outside the request path.
Telnyx retries on timeout or non-2xx. Keep your endpoint idempotent.
Webhook events
The current OpenAPI EmailWebhookEvent enum contains these exact subscribable
event types:
| Category | Event types |
|---|---|
| Outbound lifecycle | email.scheduled, email.sandbox, email.queued, email.sending, email.sent, email.delivered, email.deferred, email.bounced, email.failed |
| Engagement | email.complained, email.opened, email.clicked, email.unsubscribed |
| Inbound | email.received |
| Domain lifecycle | email_domain.created, email_domain.verified, email_domain.degraded, email_domain.suspended, email_domain.deleted |
Use exact case and punctuation. The create request requires at least one event; there is no implicit all-events subscription. PATCH replaces the event list, so include the complete desired allowlist.
List webhooks
GET /v2/email_domains/{domain_id}/webhooks
| Query parameter | Type | Required | Description |
|---|---|---|---|
domain_id | UUID path parameter | Yes | Parent domain. |
page[number] | integer | No | Offset page number; defaults to 1. |
page[size] | integer | No | Page size from 1 to 100; defaults to 25. |
sort | enum | No | created_at or -created_at. |
curl --fail-with-body --silent --show-error --get \
-H "Authorization: Bearer $TELNYX_API_KEY" \
--data-urlencode "page[number]=1" \
--data-urlencode "page[size]=25" \
--data-urlencode "sort=-created_at" \
"$TELNYX_API_BASE/email_domains/$EMAIL_DOMAIN_ID/webhooks"
Expected status: 200 with .data[] and .meta. Webhook lists use offset
pagination only.
Create a webhook
POST /v2/email_domains/{domain_id}/webhooks
| Parameter | Type | Required | Description |
|---|---|---|---|
domain_id | UUID path parameter | Yes | Parent domain. |
url | URI string | Yes | Webhook delivery destination. |
events | array of EmailWebhookEvent | Yes | Non-empty exact event allowlist. |
curl --fail-with-body --silent --show-error \
-X POST \
-H "Authorization: Bearer $TELNYX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/webhooks/email",
"events": [
"email.queued",
"email.sent",
"email.delivered",
"email.bounced",
"email.failed",
"email.received",
"email_domain.verified"
]
}' \
"$TELNYX_API_BASE/email_domains/$EMAIL_DOMAIN_ID/webhooks"
Expected status: 201. Save .data.id as EMAIL_WEBHOOK_ID.
Retrieve a webhook
GET /v2/email_domains/{domain_id}/webhooks/{id}
| Parameter | Type | Required | Description |
|---|---|---|---|
domain_id | UUID path parameter | Yes | Parent domain. |
id | UUID path parameter | Yes | Webhook to retrieve. |
curl --fail-with-body --silent --show-error \
-H "Authorization: Bearer $TELNYX_API_KEY" \
"$TELNYX_API_BASE/email_domains/$EMAIL_DOMAIN_ID/webhooks/$EMAIL_WEBHOOK_ID"
Expected status: 200. Confirm .data.domain_id matches the domain in the path.
Update a webhook
PATCH /v2/email_domains/{domain_id}/webhooks/{id}
| Parameter | Type | Required | Description |
|---|---|---|---|
domain_id | UUID path parameter | Yes | Parent domain. |
id | UUID path parameter | Yes | Webhook to update. |
url | URI string | No | New delivery destination. |
events | array of EmailWebhookEvent | No | Replacement non-empty event allowlist. |
The request may update url, events, or both. domain_id is bound at creation
and cannot be changed.
curl --fail-with-body --silent --show-error \
-X PATCH \
-H "Authorization: Bearer $TELNYX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"events": [
"email.sent",
"email.delivered",
"email.bounced",
"email.complained",
"email.opened",
"email.clicked",
"email.unsubscribed"
]
}' \
"$TELNYX_API_BASE/email_domains/$EMAIL_DOMAIN_ID/webhooks/$EMAIL_WEBHOOK_ID"
Expected status: 200. Verify the returned .data.events contains the complete
desired allowlist.
Delete a webhook
DELETE /v2/email_domains/{domain_id}/webhooks/{id}
| Parameter | Type | Required | Description |
|---|---|---|---|
domain_id | UUID path parameter | Yes | Parent domain. |
id | UUID path parameter | Yes | Webhook to delete. |
curl --fail-with-body --silent --show-error \
-X DELETE \
-H "Authorization: Bearer $TELNYX_API_KEY" \
"$TELNYX_API_BASE/email_domains/$EMAIL_DOMAIN_ID/webhooks/$EMAIL_WEBHOOK_ID"
Expected status: 200 with the deleted webhook in .data, not 204.
Additional Operations
All 13 reachable operations are indexed below. Use the inline core tasks first; for exhaustive optional parameters and response schemas, read references/api-details.md.
| # | Operation | Operation ID | Endpoint | Required params |
|---|---|---|---|---|
| 1 | List domains | listEmailDomains | GET /v2/email_domains | None |
| 2 | Create a domain | createEmailDomain | POST /v2/email_domains | domain |
| 3 | Retrieve a domain | getEmailDomain | GET /v2/email_domains/{id} | id |
| 4 | Update a domain | updateEmailDomain | PATCH /v2/email_domains/{id} | id; include at least one update field |
| 5 | Delete a domain | deleteEmailDomain | DELETE /v2/email_domains/{id} | id; force=true for a verified domain |
| 6 | Get domain health | getEmailDomainHealth | GET /v2/email_domains/{id}/health | id |
| 7 | List generated DNS records | listEmailDomainDnsRecords | GET /v2/email_domains/{domain_id}/dns_records | domain_id |
| 8 | Verify current DNS | verifyEmailDomainDnsRecords | POST /v2/email_domains/{domain_id}/verify | domain_id |
| 9 | List domain webhooks | listEmailDomainWebhooks | GET /v2/email_domains/{domain_id}/webhooks | domain_id |
| 10 | Create a domain webhook | createEmailDomainWebhook | POST /v2/email_domains/{domain_id}/webhooks | domain_id, url, events |
| 11 | Retrieve a domain webhook | getEmailDomainWebhook | GET /v2/email_domains/{domain_id}/webhooks/{id} | domain_id, id |
| 12 | Update a domain webhook | updateEmailDomainWebhook | PATCH /v2/email_domains/{domain_id}/webhooks/{id} | domain_id, id; include url, events, or both |
| 13 | Delete a domain webhook | deleteEmailDomainWebhook | DELETE /v2/email_domains/{domain_id}/webhooks/{id} | domain_id, id |
Before using lower-frequency optional parameters or branching on response fields, read the list-query section, the request schemas, and the response schemas.
Alternatives
Compare before choosing
alirezarezvani/claude-skills
app-store-optimization
App Store Optimization (ASO) toolkit for researching keywords, analyzing competitor rankings, generating metadata suggestions, and improving app visibility on Apple App Store and Google Play Store. Use when the user asks about ASO, app store rankings, app metadata, app titles and descriptions, app store listings, app visibility, or mobile app marketing on iOS or Android. Supports keyword research and scoring, competitor keyword analysis, metadata optimization, A/B test planning, launch checklist
dotnet/skills
migrate-vstest-to-mtp
Migrates .NET test projects from VSTest to Microsoft.Testing.Platform (MTP). Use when user asks to "migrate to MTP", "switch from VSTest", "enable Microsoft.Testing.Platform", "use MTP runner", set OutputType=Exe only for test projects in Directory.Build.props, or mentions EnableMSTestRunner, EnableNUnitRunner, or UseMicrosoftTestingPlatformRunner. USE FOR: MTP behavioral differences vs VSTest (exit code 8, zero tests discovered, --ignore-exit-code, TESTINGPLATFORM_EXITCODE_IGNORE); centralizing
HKUDS/Vibe-Trading
strategy-generate
Create, modify, and optimize quantitative trading strategies, then backtest and evaluate them.
K-Dense-AI/scientific-agent-skills
dask
Distributed computing for larger-than-RAM pandas/NumPy workflows. Use when you need to scale existing pandas/NumPy code beyond memory or across clusters. Best for parallel file processing, distributed ML, integration with existing pandas code. For out-of-core analytics on single machine use vaex; for in-memory speed use polars.