SDK examples

Copy-and-paste-ready snippets in three flavors. Wrap them in a thin client and you've got yourself an SDK.

Send an SMS

// lynsms.js — tiny helper library
const BASE = "https://lynsms.com/api/v1";

class LynSMS {
  constructor(apiKey) { this.apiKey = apiKey; }

  async _req(method, path, body) {
    const res = await fetch(`${BASE}${path}`, {
      method,
      headers: {
        Authorization: `Bearer ${this.apiKey}`,
        "Content-Type": "application/json",
      },
      body: body ? JSON.stringify(body) : undefined,
    });
    const json = await res.json();
    if (!json.success) {
      const e = json.error;
      throw new Error(`[${e.code}] ${e.message}`);
    }
    return json.data;
  }

  send(params)        { return this._req("POST", "/messages/send", params); }
  bulk(params)        { return this._req("POST", "/messages/bulk", params); }
  get(id)             { return this._req("GET",  `/messages/${id}`); }
  list(filters = {})  {
    const qs = new URLSearchParams(filters).toString();
    return this._req("GET", `/messages${qs ? `?${qs}` : ""}`);
  }
  balance()           { return this._req("GET",  "/balance"); }
}

// Usage:
const lynsms = new LynSMS(process.env.LYNSMS_API_KEY);
const msg = await lynsms.send({
  to: "+12025550143",
  from: "LynSMS",
  body: "Hi from LynSMS!",
});
console.log(msg.id, msg.status);
# lynsms.py — tiny helper library
import os, requests

class LynSMSError(Exception): ...

class LynSMS:
    BASE = "https://lynsms.com/api/v1"

    def __init__(self, api_key: str):
        self.session = requests.Session()
        self.session.headers.update({
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json",
        })

    def _req(self, method, path, **kwargs):
        r = self.session.request(method, f"{self.BASE}{path}", timeout=15, **kwargs)
        body = r.json()
        if not body.get("success"):
            e = body["error"]
            raise LynSMSError(f"[{e['code']}] {e['message']}")
        return body["data"]

    def send(self, **kwargs):     return self._req("POST", "/messages/send", json=kwargs)
    def bulk(self, **kwargs):     return self._req("POST", "/messages/bulk", json=kwargs)
    def get(self, message_id):    return self._req("GET",  f"/messages/{message_id}")
    def list(self, **filters):    return self._req("GET",  "/messages", params=filters)
    def balance(self):            return self._req("GET",  "/balance")


# Usage:
lynsms = LynSMS(os.environ["LYNSMS_API_KEY"])
msg = lynsms.send(to="+12025550143", from_="LynSMS", body="Hi from LynSMS!")
print(msg["id"], msg["status"])
curl https://lynsms.com/api/v1/messages/send \
  -H "Authorization: Bearer $LYNSMS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to":   "+12025550143",
    "from": "LynSMS",
    "body": "Hi from LynSMS!"
  }'

Check message status

const message = await lynsms.get(messageId);

switch (message.status) {
  case "pending":   /* not yet sent */         break;
  case "sent":      /* accepted by provider */ break;
  case "delivered": /* confirmed by carrier */ break;
  case "failed":
    console.error("Failed:", message.error?.message);
    break;
}
message = lynsms.get(message_id)

if message["status"] == "failed":
    print("Failed:", message["error"]["message"])
elif message["status"] == "delivered":
    print("Delivered at:", message["delivered_at"])
curl https://lynsms.com/api/v1/messages/msg_VyB2pNkX0wnA9aTrLqDh1Z3Fc \
  -H "Authorization: Bearer $LYNSMS_API_KEY"

Handle a webhook event

import crypto from "node:crypto";
import express from "express";

const app = express();

app.post(
  "/webhooks/lynsms",
  express.raw({ type: "application/json" }),
  (req, res) => {
    const header = req.header("LynSMS-Signature");
    const [t, v1] = header.split(",").map(s => s.split("=")[1]);

    const expected = crypto
      .createHmac("sha256", process.env.LYNSMS_WEBHOOK_SECRET)
      .update(`${t}.${req.body.toString()}`)
      .digest("hex");

    if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1))) {
      return res.status(400).send("invalid signature");
    }

    const event = JSON.parse(req.body.toString());
    // Always ack quickly. Do the real work in a queue.
    queue.publish("lynsms.events", event);
    res.sendStatus(200);
  }
);

app.listen(3000);
import os, hmac, hashlib, json
from flask import Flask, request, abort

app = Flask(__name__)
SECRET = os.environ["LYNSMS_WEBHOOK_SECRET"].encode()

@app.post("/webhooks/lynsms")
def lynsms_webhook():
    raw = request.get_data()
    header = request.headers.get("LynSMS-Signature", "")
    parts = dict(p.split("=", 1) for p in header.split(","))
    expected = hmac.new(
        SECRET,
        f"{parts['t']}.{raw.decode()}".encode(),
        hashlib.sha256,
    ).hexdigest()

    if not hmac.compare_digest(expected, parts["v1"]):
        abort(400, "invalid signature")

    event = json.loads(raw)
    # Enqueue and return 200 fast.
    queue.publish("lynsms.events", event)
    return "", 200
Official SDKs. Native libraries for Node.js, Python, PHP, and Go are on the roadmap. Until then, the snippets above are the canonical way to use the API.