lang_undefined
lang_undefined
lang_undefined
- Pair an Android phone in your dashboard (Devices, Add device, scan the QR code) and copy its device ID.
- Create an API key under Tools, API Keys, with the sms_send permission (and wa_send for WhatsApp). Copy the secret into an environment variable; never into source.
- Python 3.8+ with requests installed: pip install requests.
lang_undefined
Copy this into a module. It reads the secret and device ID from environment variables, sends as a form body, and raises on any non-200 status in the JSON.
import os
import requests
SHARKSMS = "https://sharksms.com/api"
SECRET = os.environ["SHARKSMS_SECRET"] # from Tools -> API Keys
DEVICE = os.environ["SHARKSMS_DEVICE"] # from Devices -> Android
def send_sms(phone: str, message: str, sim: int = 1) -> int:
"""Queue one SMS on your paired phone. Returns the message id."""
r = requests.post(
f"{SHARKSMS}/send/sms",
data={ # form body, not json=
"secret": SECRET,
"mode": "devices",
"device": DEVICE,
"sim": sim,
"phone": phone,
"message": message,
},
timeout=15,
)
body = r.json() # HTTP is always 200; read status
if body["status"] != 200:
raise RuntimeError(f"SharkSMS {body['status']}: {body['message']}")
return body["data"]["messageId"]
def sms_status(message_id: int) -> str:
r = requests.get(
f"{SHARKSMS}/get/sms.message",
params={"secret": SECRET, "id": message_id, "type": "sent"},
timeout=15,
)
return r.json()["data"]["status"] # queued | pending | sent | failed
if __name__ == "__main__":
mid = send_sms("+15551234567", "Hi Maria, reminder: your cut is tomorrow at 3:30pm. Reply C to cancel.")
print("queued as", mid, "->", sms_status(mid))
WhatsApp is the same shape: a different endpoint, your linked account ID, and recipient instead of phone.
def send_whatsapp(recipient: str, message: str) -> int:
r = requests.post(f"{SHARKSMS}/send/whatsapp", data={
"secret": SECRET,
"account": os.environ["SHARKSMS_WA_ACCOUNT"],
"recipient": recipient, # +1555... or a group id ending @g.us
"type": "text",
"message": message,
}, timeout=15).json()
if r["status"] != 200:
raise RuntimeError(r["message"])
return r["data"]["messageId"]
lang_undefined
Send to your own phone first. Then call GET /api/get/sms.message with the returned messageId and type=sent and watch it go queued, sent. If it stays queued, the paired phone is off, offline or battery-optimised; see the Android gateway page.
lang_undefined
- The API reads a form body, not JSON. A JSON body is ignored and you get status 400 for missing parameters.
- HTTP is always 200. Branch on the JSON status field, never on the HTTP status.
- No deduplication. A retry after a timeout can send twice; record the messageId on success and check status before resending.
- requests.post(..., json=...) sets a JSON body, which the API does not read. Use data= as in the example.