====== voip.ms SMS/MMS REST API ====== Reference for the voip.ms SMS/MMS REST API. Sanitized — no account credentials or phone numbers. Account-specific values (API username/password, DID numbers) are supplied at runtime via environment variables and kept local. ===== Endpoint & authentication ===== * **Base URL:** ''https://voip.ms/api/v1/rest.php'' (use ''voip.ms'', **not** ''www.voip.ms'' — the ''www'' host 302-redirects and drops POST bodies, producing ''missing_method''). * **Auth (every request):** ''api_username'', ''api_password'', ''method''. - ''api_username'' is the **portal login email** — //not// the 6-digit account ID. - ''api_password'' is set under **Main Menu → SOAP / REST API → API Security** and is distinct from the portal login password. - The calling server's public IP must be **whitelisted** on the same API Security page. * **Transport:** GET with query params for SMS; POST ''multipart/form-data'' for MMS with base64 images. * A separate **bearer token / API key** exists for the 3CX webhook flow — it is **not** used by ''rest.php''. ===== Limits & pricing ===== * **API sending cap: 100 SMS/MMS per day** (portal is unlimited). Raise via support ticket. * **SMS:** $0.0075 each way. **MMS:** $0.02 each way. * US/Canada 10-digit DIDs only; short codes and 2FA codes aren't guaranteed; public URL shorteners (bit.ly etc.) may be blocked. * MMS attachments: types ''JPG, GIF, JPEG, PNG, MP3, WAV, MIDI, MP4, 3GP''; ≤1300 KB each; up to 3 files; text ≤2048 chars. ===== Methods ===== ==== sendSMS — send a text ==== ^ Param ^ Req ^ Notes ^ | did | yes | Sender DID, e.g. ''5551234567'' | | dst | yes | Destination number | | message | yes | Max **160** chars | Returns ''{"status":"success","sms":}''. Requires SMS enabled on the DID (see ''setSMS'' below), else ''{"status":"sms_failed","message":"The SMS message was not sent"}''. ==== sendMMS — send media/text ==== ^ Param ^ Req ^ Notes ^ | did | yes | Sender DID | | dst | yes | Destination | | message | yes | Max **2048** chars | | media1 | no | URL to a media file | | media2 | no | Base64 image (''data:image/png;base64,...'') | | media3 | no | Reserved/empty | * POST + base64 → up to **1.2 MB/file**; GET + base64 → ~160 KB (~512-char URL limit). File-URL submissions have no size limit either way. ==== getSMS — list/retrieve texts ==== ^ Param ^ Req ^ Notes ^ | sms | no | ID for a specific SMS | | from | no | Start date ''YYYY-MM-DD'' (default: today) | | to | no | End date (default: today) | | type | no | ''1''=received, ''0''=sent | | did | no | Filter by DID | | contact | no | Filter by contact number | | limit | no | Records to return (default **50**) | | timezone | no | Numeric -12 to 13 | | all_messages | no | ''1'' = SMS + MMS combined, ''0'' = SMS only (id must be ''0'' when set) | Returns ''{"status":"success","sms":[ ...rows... ]}''. **Empty result returns ''{"status":"no_sms","message":"There are no SMS messages"}''** — treat as ''[]'', not an error. ==== getMMS — list/retrieve media messages ==== Same shape as ''getSMS'' but the id param is ''mms''. ''all_messages=1'' returns MMS+SMS combined (id must be ''0''). Empty result also reports ''status: no_sms''. ==== getMediaMMS — fetch attachments for a message ==== ^ Param ^ Req ^ Notes ^ | id | yes | MMS id | | media_as_array | no | ''1''=array, ''0''=JSON object (default) | Returns ''{"status":"success","id":...,"date":...,"media":[url,...]}'' (up to 3 slots). ==== deleteSMS / deleteMMS — delete one message ==== ^ Param ^ Req ^ Notes ^ | id | yes | Message id | Returns ''{"status":"success"}''. ==== setSMS — enable/disable SMS on a DID ==== ^ Param ^ Req ^ Notes ^ | did | yes | DID to update | | enable | yes | ''1'' to enable, ''0'' to disable | | email_enabled | no | bool — forward inbound SMS to email | | email_address | no | email address(es), comma-separated | | sms_forward_enable | no | bool — forward inbound SMS to another number | | sms_forward | no | forwarding number | | url_callback_enable | no | bool — GET callback on inbound | | url_callback | no | callback URL (variables below) | | url_callback_retry | no | bool — require ''ok'' response, retry every 30 min | SMS must be enabled on a DID (''enable=1'') before ''sendSMS'' works. ==== getDIDsInfo — list DIDs on the account ==== Returns ''{"status":"success","dids":[ ... ]}''. Each DID includes ''sms_available'', ''sms_enabled'', ''mms_available'', and the full SMS config fields — use this to find a SMS-capable DID and check whether SMS is enabled. Note: ''getDIDs'', ''getDIDInfo'', ''getDID'' are **not** valid methods — use ''getDIDsInfo''. ===== Inbound via URL Callback (per-DID) ===== Configure on the DID (portal Manage DID, or ''setSMS''): https://your.host/sms?to={TO}&from={FROM}&message={MESSAGE}&id={ID}&date={TIMESTAMP}&media={MEDIA} Variables: ''{ID}'', ''{TIMESTAMP}'', ''{FROM}'', ''{TO}'', ''{MESSAGE}'', ''{MEDIA}'' (comma-separated media list, for MMS). **Retry:** if "URL Callback Retry" is enabled, your endpoint must respond with the literal body ''ok''. Without it, voip.ms re-sends the same message **every 30 minutes**. ===== Dialing mode (per-DID, for 3CX/API) ===== Choose NANPA (10-digit, no country code) or E164 (''+1'' + 10 digits). Affects what you send to the API and what arrives in callbacks — normalize on your side. ===== Gotchas ===== * ''api_username'' is the portal **email**, not the account ID. * Empty ''getSMS''/''getMMS'' results report ''status: no_sms'' (even for MMS) — return ''[]''. * SMS must be enabled per-DID (''setSMS enable=1'') before sending, else ''sms_failed''. * ''sendSMS''/''sendMMS'' reuse the ''sms'' response key for the new message id (int); ''getSMS'' uses ''sms'' for the row list; ''getMMS'' uses ''mms''. * No ''markSMSRead'' method exists. * SIP/SMS over SIP MESSAGE is text-only (no MMS) and uses a separate SIP sub-account, not the REST API. * DID **POP must match** the registered SIP server or inbound calls won't ring. * Transient transport errors occur; clients should retry with backoff. ===== Other ingestion channels (non-REST) ===== * **Email to SMS:** mail ''sms@voip.ms'', subject = recipient 10-digit number; security-code / from-DID overrides via dot syntax ''dst.seccode.fromdid''. * **SMPP:** ''smpp.voip.ms:2775'' (plain) / '':3550'' (TLS, scheme ''ssmpp''); bind as transceiver; ''source_addr'' = SMS-enabled DID. Bypasses the 100/day REST cap. * **SIP MESSAGE (RFC 3428):** SMS only, user/pass-auth trunks; original destination in ''X-Sms-To'' header on receive. ---- //Source: voip.ms official API docs (''/m/apidocs.php'') + SMS/MMS wiki article, verified live.//