Gateman
Documentation/Send SMS

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:

FieldContract
ToRequired single E.164 recipient.
FromRequired 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.
MessagingServiceSidRequired unless From is supplied. Must match MG followed by 32 hexadecimal characters.
BodyRequired, non-empty string, at most 1,600 bytes by PHP byte length.
StatusCallbackOptional 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:

FieldContract
toRequired single E.164 recipient or 3–8 digit short code.
fromOptional sender; required when messaging_profile_id is absent. Must not contain CR/LF.
messaging_profile_idOptional profile; required when from is absent. Must not contain CR/LF.
textRequired non-empty string. Gateman enforces no maximum length.
webhook_urlOptional HTTP/HTTPS URL with a valid host.
webhook_failover_urlOptional HTTP/HTTPS URL with a valid host.
use_profile_webhooksOptional boolean.
typeOptional; if present, must be SMS.
auto_detectOptional boolean.
send_atOptional string passed to Telnyx.
encodingOptional 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

EnvironmentExecutionCredentialsAccounting
productionSelected provider is invoked.Applicable provider credentials are required.One accepted request consumes one operation.
stagingValidates, then captures locally.Provider credentials are not required for capture.One accepted capture consumes one operation.
developmentValidates, 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

ConditionResponse
Authentication, stale signature, or missing scopeHTTP 401 with the authentication error, including Scope not allowed where applicable.
Invalid JSONHTTP 400 Invalid JSON.
Missing/unsupported environmentHTTP 400 Application environment is required or Unsupported application environment.
Gateman boundary validation failureHTTP 400 with the provider-specific validation message.
Application concurrencyHTTP 429/503 app_concurrency_limit_exceeded or app_concurrency_guard_unavailable.
Provider concurrencyHTTP 429/503 Too many concurrent provider requests or Provider concurrency guard unavailable.
Monthly allowance exhaustedHTTP 403 monthly_operation_limit_reached.
Accounting unavailableHTTP 503 Operation accounting unavailable.
Provider credentials unavailableHTTP 503 sms_provider_unavailable.
Twilio/Telnyx provider HTTP errorNative provider status/body and selected headers.
Unkeyed Twilio transport/runtime failureHTTP 502 Twilio request failed.
Unkeyed Telnyx transport/runtime failureHTTP 502 Telnyx request failed.
Keyed uncertain Twilio/Telnyx executionHTTP 409 sms_send_indeterminate.
AWS definite rejectionHTTP 502 with AWS SendTextMessage rejected the request and an AWS error code.
AWS uncertain execution with idempotencyHTTP 409 sms_send_indeterminate.
Idempotency payload conflictHTTP 409 idempotency_key_payload_conflict.
Local capture failureHTTP 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.send and 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 environment and 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 -->