Before sending
Send an SMS or supported MMS using a sending number configured for your account. This is a production operation that can contact recipients and create charges. Use only authorized recipients and approved traffic; the example numbers and reference below are fictional.
Your account needs outbound messaging approval and the applicable sender, country and traffic permissions. Direct Personal/Consumer user credentials are not eligible for this API. Approved dedicated API credentials have a separate eligibility path; mobile P2P senders can require additional P2P and US/Canada permissions. Confirm the correct account setup with MultiTEL instead of treating an API credential as automatic permission to send any traffic.
Send request
Authenticate over HTTPS with an enabled API account from its allowed source IP address. Keep credentials in server-side secret storage. Use POST with form-encoded fields, or a JSON object when no form or query fields are supplied. Do not put credentials or message text in a URL.
curl --silent --show-error --user "$API_USER:$API_PASSWORD" \
--data-urlencode 'from=12025550123' \
--data-urlencode 'to=12025550124' \
--data-urlencode 'text=Your requested update is ready.' \
--data-urlencode 'reference=order-update-example' \
https://api.multitel.net/v3/sendsms| Field | Required | Meaning |
|---|---|---|
| from | Yes | Your configured sending number, preferably full international digits. |
| to | Yes | One destination, comma-separated destinations or a JSON array. Prefer full international digits. A group request can be rejected by its applicable P2P/country limits; it is not an unrestricted bulk-send API. |
| text | For SMS | UTF-8 message text. At least nonempty text or media is required. Send actual characters and line breaks rather than HTML or percent-escaped text. Some carrier paths normalize literal escape strings. |
| media | For media-only MMS | Base64-encoded media contents, not a URL or file path. MMS availability, format and size depend on the configured route. Confirm supported media with MultiTEL; no universal media-size limit is established by this handler. |
| reference | Recommended | Your correlation label, retained in records/callbacks. Include one for troubleshooting. It is not an idempotency key. |
| notifyurl | No | Your HTTPS callback receiver. The handler can POST an initial result after processing. It must be a receiver you control, and must not be an internal-service URL. |
For a JSON array, use a real array in to; do not put a JSON array string inside a form field. Keep single-recipient sending as the initial integration test. Group and MMS support differ by route, so confirm the supported combination before using them.
Read the complete result
Illustrative selected fields only; the displayed cost is not a quote.
{
"status": {
"code": "200",
"msg": ""
},
"response": {
"sms_log_id_ori": 42,
"to": "12025550124",
"from": "12025550123",
"status": "Success",
"message": "Message queued",
"causecode": 0,
"uniqueid": "fixture-message",
"cost": "$0.0120",
"carrier_fee_usd": "0.0020000000",
"chars": 31,
"parts": 1,
"encoding": "GSM-7",
"permsg": "$0.0120",
"pid": "fixture-reference"
}
}Check HTTP status, JSON status.code and the response’s status/message together. Result codes can be strings. Keep sms_log_id_ori and the returned message/reference values for support correlation. Legacy uniqueid and pid values vary by route; do not derive their format or assume they are client idempotency tokens.
Success or Message queued normally describes acceptance by the selected route, not receipt by a person’s handset. An initial callback status such as sent does not by itself establish final delivery.
Segments and charges
Use SMS length analysis on the complete final text before sending. SMS prices depend on the destination and account service; applicable carrier fees are added per segment. The send path combines recipient prices and applicable fees, then multiplies by the calculated SMS segment count. It treats an MMS request as one message for this calculation.
cost and permsg are formatted monetary strings in the legacy response. carrier_fee_usd reports the carrier-fee component in USD and is already included in the computed send total; do not add it a second time. Actual account pricing and route availability must be checked for your account. The request is not a price-only operation.
The reviewed code debits after its successful carrier-send path, but carrier acceptance, local persistence and billing are not one transaction. An error or timeout can occur after an upstream request was accepted. No client idempotency key is exposed: repeating the same reference can send and charge again.
Local delivery and mixed results
Numbers hosted locally can be accepted into MultiTEL’s inbound messaging flow without an external carrier send. For an all-local request, the response can include accepted, message_id, provider and delivery_status. Local acceptance does not guarantee that the recipient’s configured forwarding destination worked.
Inspect local_delivery_results and partial when present. A recipient can show accepted true while its forwarding result is unsuccessful. A mixed request can have accepted carrier recipients and a failed local portion. Do not retry the whole batch automatically: reconcile each recipient first.
All-local acceptance reports zero outbound cost in this path, while recipients can still incur their normal inbound messaging charges. Do not interpret a zero outbound cost as a guarantee that no account is charged.
Callbacks and correlation
When notifyurl is supplied, the initial callback has a status envelope and response fields including message_id, reference, from, to, status, status_text, error_code, timestamp and accepted. Local results can also be present. Store correlation information without logging API credentials or unnecessary message contents.
This handler does not add a signing field to that initial callback. Do not use an unverified callback as standalone authorization for another action. Consult the supported integration/webhook setup for your account and reconcile uncertain results with portal records or support. Do not assume callbacks arrive once or in final-delivery order.
Failures and safe recovery
Validation failures can use API code 403. Account approval, P2P and country policy denials may also set HTTP 403 and include a machine-readable response.code. Rate limits can use 429 with retry information. An unavailable policy or a send/local persistence failure can use 503 or 500; legacy insufficient balance can also return 500.
For 429, respect Retry-After and any response.retry_after value. For account, sender, country or recipient rejection, correct the cause before retrying. For a timeout or unclear send result, preserve the request time, reference and returned identifiers, inspect the portal and contact support before resending. An absent log entry alone is not proof that no carrier accepted the request.