Send SMS
capability_id: sms.send
display_name: Send SMS
ui_capability_key: send_sms
scope: sms.send
endpoints:
- provider: twilio
method: POST
path: /twilio/sms/send
- provider: telnyx
method: POST
path: /telnyx/sms/send
- provider: aws
method: POST
path: /aws/sms/send
operations:
twilio: twilio.sms.send
telnyx: telnyx.sms.send
aws: aws.sms.send
billable: true
environment: required
Purpose and authorization
sms.send lets an authenticated Gateman application submit native SMS requests through configured Twilio, Telnyx, or AWS End User Messaging SMS. The application selects the provider by choosing its endpoint.
Every request MUST use authenticated Contract v1 transport and the sms.send scope. Provider credentials are managed by Gateman and MUST NOT be supplied by the application.
Gateman authenticates, authorizes, accounts for, validates the supported boundary of, and relays the operation. The provider remains responsible for native processing, routing, segmentation, carrier handling, and delivery. Gateman does not provide a provider-neutral composer, contact-list manager, sending queue, automatic failover, opt-out system, or handset-delivery guarantee.
Implementation contract
Common request rules
All SMS routes are authenticated JSON POST requests. Contract v1 signing, timestamps, raw-body handling, and authentication errors are defined by Contract v1 and Authentication.
POST /twilio/sms/send
Content-Type: application/json
X-GM-App: app_example
X-GM-Ts: 1791748800
X-GM-Sig: <Contract-v1-signature>
X-GM-Idempotency-Key: order-sms-123
X-GM-Idempotency-Key is optional and is included in the Contract v1 signature when supplied. Every request MUST include environment with one of production, staging, or development. Gateman lowercases and trims this value, then removes it before provider execution. Direct HTTP integrations MUST include it; official PHP, Node.js, Python, and Go clients can inject it.
Provider selection is endpoint-based. Each endpoint accepts only its listed provider-native fields. Unsupported JSON fields are rejected. Each request supports one recipient; recipient arrays and bulk expansion are not supported.
Twilio: POST /twilio/sms/send
Supported native fields:
| Field | Contract |
|---|---|
To | Required single E.164 recipient. |
From | Required unless MessagingServiceSid is supplied. Accepts E.164, a 3–11 character alphanumeric sender ID, or a 3–8 digit short code. Colon-containing values are rejected. |
MessagingServiceSid | Required unless From is supplied. Must match MG followed by 32 hexadecimal characters. |
Body | Required, non-empty string, at most 1,600 bytes by PHP byte length. |
StatusCallback | Optional HTTP/HTTPS URL with a valid host; hosts containing _ are rejected. |
All supplied Twilio field values must be non-empty strings, at most 4,096 bytes, and must not contain CR or LF. Other fields are rejected.
{
"environment": "production",
"To": "+15551234567",
"From": "+15557654321",
"Body": "Your example verification code is 482901.",
"StatusCallback": "https://app.example.test/sms/twilio-status"
}
Gateman forwards a native Twilio Message create request. It does not calculate GSM-7/UCS-2 encoding or provider segments. The 1,600-byte check is not a provider-calculated segment count.
Telnyx: POST /telnyx/sms/send
Supported native fields:
| Field | Contract |
|---|---|
to | Required single E.164 recipient or 3–8 digit short code. |
from | Optional sender; required when messaging_profile_id is absent. Must not contain CR/LF. |
messaging_profile_id | Optional profile; required when from is absent. Must not contain CR/LF. |
text | Required non-empty string. Gateman enforces no maximum length. |
webhook_url | Optional HTTP/HTTPS URL with a valid host. |
webhook_failover_url | Optional HTTP/HTTPS URL with a valid host. |
use_profile_webhooks | Optional boolean. |
type | Optional; if present, must be SMS. |
auto_detect | Optional boolean. |
send_at | Optional string passed to Telnyx. |
encoding | Optional auto, gsm7, or ucs2. |
Unknown fields and invalid field types are rejected. Remaining native message, sender, encoding, scheduling, destination, and account restrictions are determined by Telnyx.
{
"environment": "production",
"to": "+15551234567",
"messaging_profile_id": "40000000-0000-0000-0000-000000000001",
"text": "Your example verification code is 482901.",
"type": "SMS",
"encoding": "auto",
"webhook_url": "https://app.example.test/sms/telnyx-status"
}
AWS End User Messaging SMS: POST /aws/sms/send
The route invokes AWS SendTextMessage through the AWS SDK. Supported native fields are:
DestinationPhoneNumber, OriginationIdentity, MessageBody, MessageType, Keyword, ConfigurationSetName, MaxPrice, TimeToLive, Context, DestinationCountryParameters, DryRun, ProtectConfigurationId, and MessageFeedbackEnabled.
Gateman validates only that unknown fields are absent, DestinationPhoneNumber is a non-empty string, and MessageBody—when provided—is a string. Gateman does not require MessageBody, validate E.164, enforce segment limits, validate sender identity, or validate every native AWS parameter combination.
{
"environment": "production",
"DestinationPhoneNumber": "+15551234567",
"OriginationIdentity": "arn:aws:sms-voice:us-east-1:000000000000:phone-number/example",
"MessageBody": "Your example verification code is 482901.",
"MessageType": "TRANSACTIONAL",
"DryRun": true
}
This endpoint returns a Gateman JSON envelope rather than a transparent raw HTTP response relay.
Environment behavior
| Environment | Execution | Credentials | Accounting |
|---|---|---|---|
production | Selected provider is invoked. | Applicable provider credentials are required. | One accepted request consumes one operation. |
staging | Validates, then captures locally. | Provider credentials are not required for capture. | One accepted capture consumes one operation. |
development | Validates, then captures locally. | Provider credentials are not required for capture. | One accepted capture consumes one operation. |
Staging and development do not use provider sandbox APIs and do not send an SMS. Authorized console users can inspect captures, which are retained for seven days. There is no customer-facing SMS capture API.
{
"ok": true,
"staged": true,
"sent": false,
"provider_accepted": false,
"delivery_status": "not_sent",
"message_id": null,
"capture_id": "01J00000000000000000000000",
"provider": "twilio",
"environment": "staging"
}
The capture ID is only a Gateman correlation value.
Provider responses and delivery meaning
Twilio and Telnyx production responses preserve the native provider HTTP status and body. Gateman forwards only these selected headers when present: content-type, the provider request ID (twilio-request-id or telnyx-request-id), and request-id. The body is not converted into a common SMS schema.
AWS success returns a Gateman envelope containing AWS SDK result data:
{
"ok": true,
"result": { "MessageId": "provider-message-id-example" }
}
Gateman acceptance, provider API acceptance, carrier processing, and handset receipt are distinct states. A successful response confirms local capture or provider API acceptance only. Gateman has no production SMS ledger and no SMS delivery-status API.
Operation accounting, idempotency, and replay obligations
Idempotency
The key is optional. Surrounding ASCII spaces and tabs are trimmed; an empty key is omitted. A non-empty key must be at most 255 bytes and contain no ASCII control characters or DEL.
The scope is:
application + provider + environment + idempotency key
The fingerprint includes the provider, environment, and complete native payload. A retained terminal result replays its HTTP status, body, and selected headers without a new provider request or operation. Changed payloads return HTTP 409 idempotency_key_payload_conflict. Concurrent, unresolved, or uncertain execution returns HTTP 409 sms_send_indeterminate.
Pre-admission provider-concurrency, monthly-limit, and accounting rejections release the current claim. Terminal successful and definite-failure results are retained for 15 minutes. Indeterminate and unresolved claims remain protected. A caller MUST NOT create a new key to bypass uncertainty unless it deliberately accepts possible duplicate sending. Official clients do not automatically retry provider operations.
Accounting and limits
Billable operation types are twilio.sms.send, telnyx.sms.send, and aws.sms.send. Each accepted production submission or nonproduction capture consumes one Gateman operation. This is not one SMS segment or one provider charge. Invalid requests, authentication failures, monthly-limit rejection, and relevant pre-reservation concurrency rejection do not consume an operation. Failures after reservation remain billable.
Application admission can return HTTP 429 app_concurrency_limit_exceeded with Retry-After, or HTTP 503 app_concurrency_guard_unavailable. Production provider-bound admission can return HTTP 429 Too many concurrent provider requests with Retry-After: 1, or HTTP 503 Provider concurrency guard unavailable. The provider-bound limit is two concurrent requests per application. Monthly exhaustion returns HTTP 403 monthly_operation_limit_reached; accounting failure returns HTTP 503 Operation accounting unavailable.
An idempotent replay does not initiate another provider request or consume another operation.
Encoding and segmentation
Gateman does not calculate GSM-7/UCS-2 segments, split messages, expand one request into multiple recipients, or calculate provider charges. Telnyx's encoding field is passed as a native option; Twilio and AWS encoding remain provider-native. A long or Unicode message may create multiple provider-billed segments even though Gateman counts one accepted operation.
Callbacks and delivery tracking
Twilio supports caller-supplied StatusCallback. Telnyx supports webhook_url, webhook_failover_url, and use_profile_webhooks. AWS has no Gateman-managed SMS callback receiver or tracking API.
Gateman does not receive, verify, forward, store, or correlate delivery callbacks. Applications own callback endpoint security, provider verification, duplicates, retries, and message-ID correlation. Captured nonproduction SMS does not create provider callbacks. See Webhooks and event handling.
Provider configuration and responsibility boundaries
Credentials are configured per application. Twilio requires an account identity, API key identity, and API key secret; Telnyx requires an API key; AWS SMS requires a region, access key ID, and secret access key, with an optional session token. AWS SMS credentials are distinct from SES credentials.
Gateman does not provision Twilio senders or messaging services, Telnyx messaging profiles, AWS SMS resources, sender registrations, or callback infrastructure. There is no dedicated SMS readiness endpoint.
Provider and carrier requirements for sender identity, destination eligibility, registration, throughput, content, consent, and opt-out handling remain the application's and provider's responsibility. Gateman does not manage STOP/ START handling, suppression lists, consent records, or contacts.
Error outcomes
| Condition | Response |
|---|---|
| Authentication, stale signature, or missing scope | HTTP 401 with the authentication error, including Scope not allowed where applicable. |
| Invalid JSON | HTTP 400 Invalid JSON. |
| Missing/unsupported environment | HTTP 400 Application environment is required or Unsupported application environment. |
| Gateman boundary validation failure | HTTP 400 with the provider-specific validation message. |
| Application concurrency | HTTP 429/503 app_concurrency_limit_exceeded or app_concurrency_guard_unavailable. |
| Provider concurrency | HTTP 429/503 Too many concurrent provider requests or Provider concurrency guard unavailable. |
| Monthly allowance exhausted | HTTP 403 monthly_operation_limit_reached. |
| Accounting unavailable | HTTP 503 Operation accounting unavailable. |
| Provider credentials unavailable | HTTP 503 sms_provider_unavailable. |
| Twilio/Telnyx provider HTTP error | Native provider status/body and selected headers. |
| Unkeyed Twilio transport/runtime failure | HTTP 502 Twilio request failed. |
| Unkeyed Telnyx transport/runtime failure | HTTP 502 Telnyx request failed. |
| Keyed uncertain Twilio/Telnyx execution | HTTP 409 sms_send_indeterminate. |
| AWS definite rejection | HTTP 502 with AWS SendTextMessage rejected the request and an AWS error code. |
| AWS uncertain execution with idempotency | HTTP 409 sms_send_indeterminate. |
| Idempotency payload conflict | HTTP 409 idempotency_key_payload_conflict. |
| Local capture failure | HTTP 503 SMS staging capture unavailable. |
The fixed Twilio and Telnyx transport messages are the public responses for unexpected unkeyed runtime failures. Internal exception messages are not public. A transport failure does not prove that no SMS was accepted.
Retention and data handling
Production SMS bodies are not stored in a Gateman SMS ledger. Nonproduction captures contain recipient, sender projection, message content, native payload, provider, environment, and capture metadata and are available to authorized console users for seven days.
Definite terminal SMS idempotency results are retained for 15 minutes. Indeterminate and unresolved claims remain protected. Operation accounting is separate from capture and idempotency retention. Provider-side retention is independent of Gateman. Gateman does not provide SMS suppression, opt-out, consent-record, or contact-list management.
Implementation outcome
A conforming integration authenticates with Contract v1 and sms.send, selects the intended provider endpoint, submits that provider's native shape and environment, handles its response format, distinguishes provider acceptance from handset delivery, treats nonproduction capture as non-delivery, uses idempotency appropriately, avoids blind retries after sms_send_indeterminate, accounts for one operation per accepted request, and handles delivery callbacks independently when configured.
Implementation instructions for agents
- An integration SHOULD use an official Gateman PHP, Node.js, Python, or Go client where appropriate. Direct HTTP implementations MUST conform to Contract v1.
- The integration MUST use
sms.sendand select exactly one of the three provider endpoints. - It MUST preserve provider-native field names and structures and MUST NOT invent a universal SMS payload.
- It MUST supply a valid
environmentand treat nonproduction capture as non-delivery. - It MUST distinguish Gateman operations from provider segmentation and provider charges.
- It SHOULD use a stable idempotency key where duplicate sending matters and MUST NOT blindly retry or create a new key after unresolved execution.
- It MUST NOT assume official clients retry automatically or that Gateman provides delivery tracking/callback processing.
- It MUST implement its own callback receiver and verification when using provider callbacks.
Reusable AGENTS.md block
<!-- gateman:begin capability=sms.send -->
- Send SMS with authenticated Contract v1 and the `sms.send` scope.
- Select exactly one native provider endpoint: `/twilio/sms/send`,
`/telnyx/sms/send`, or `/aws/sms/send`.
- Include `environment`: production invokes the provider; staging/development
capture locally and do not send an SMS.
- Handle Twilio/Telnyx native responses and the AWS `{ok, result}` envelope.
- One accepted request or capture consumes one Gateman operation; this is not
one provider segment or provider-side charge.
- `X-GM-Idempotency-Key` is optional and scoped by application, provider,
environment, and key. Preserve the same key and payload for replay.
- Treat `sms_send_indeterminate` as unresolved provider execution. Do not
blindly retry or create a new key to bypass uncertainty. Official clients
do not automatically retry.
- Gateman does not provide delivery tracking or callback processing. Applications
using callbacks own endpoint security, verification, retries, duplicates,
and message correlation.
- Full reference: https://docs.getgateman.com/capabilities/sms.send/
<!-- gateman:end capability=sms.send -->
