Integration

Send SMS from Python through your own Android phone

Twenty lines of requests, no SDK, no carrier account. Your script POSTs to SharkSMS, the phone you paired sends the text on its own SIM plan, and you get a message ID back to check delivery. WhatsApp is the same call with two parameters changed.

Form-encoded POST, JSON back, HTTP always 200. Read the status field.

  • 1 requestPOST /api/send/sms with secret, device, phone, message.
  • 0 per messageSends ride on the SIM plan of the phone you paired.
  • 5 secondsWebhook timeout for replies. Ack fast, work later.

lang_undefined

lang_undefined

lang_undefined · lang_undefined REST API

lang_undefined

  1. Pair an Android phone in your dashboard (Devices, Add device, scan the QR code) and copy its device ID.
  2. 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.
  3. 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.

Straight answers

Do I need an SDK?

No. It is one HTTPS POST with a form body. Any language that can make an HTTP request can send. The snippets on this page are complete.

Can my code receive replies?

Yes. Add a webhook under Tools, Webhooks and every incoming SMS or WhatsApp message is POSTed to your URL as a form body with the sender, the text and a timestamp. See the webhooks reference.

Does this work from Django or Flask?

Yes; it is a plain function. Call it from a view, a Celery task or a management command. For anything user-facing, send from a background task so a slow phone never blocks a web request.