first commit

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
chelsea
2026-07-04 04:39:53 +00:00
commit db5bde0a70
13 changed files with 1095 additions and 0 deletions

View File

@@ -0,0 +1,135 @@
====== 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":<new id>}''. 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''):
<code>
https://your.host/sms?to={TO}&from={FROM}&message={MESSAGE}&id={ID}&date={TIMESTAMP}&media={MEDIA}
</code>
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.//

152
sms/docs/voipms-sms-api.md Normal file
View File

@@ -0,0 +1,152 @@
# 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, etc.)
are kept local and supplied at runtime via environment variables.
## 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":<new id>}`. 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.*