Client SDKs
Official client libraries for Python, JavaScript/TypeScript, and Go.
The Vendel SDKs provide a simple interface for sending SMS, checking quotas, and verifying
webhook signatures. They authenticate with integration API keys (vk_ prefix)
— create one in the Dashboard under Settings → API Keys.
Installation
Python
pip install vendel-sdk JavaScript / TypeScript
npm install vendel-sdk
Zero runtime dependencies — uses built-in fetch (Node 18+). TypeScript types included.
Go
go get github.com/JimScope/vendel-sdk-go Quick start
Send an SMS in three lines:
Python
from vendel_sdk import VendelClient
client = VendelClient("https://app.vendel.cc", "vk_your_api_key")
response = client.send_sms(["+1234567890"], "Hello from Vendel!") JavaScript / TypeScript
import { VendelClient } from "vendel-sdk";
const client = new VendelClient({
baseUrl: "https://app.vendel.cc",
apiKey: "vk_your_api_key",
});
const response = await client.sendSms(["+1234567890"], "Hello from Vendel!"); Go
package main
import (
"context"
"fmt"
vendel "github.com/JimScope/vendel-sdk-go"
)
func main() {
client := vendel.NewClient("https://app.vendel.cc", "vk_your_api_key")
resp, err := client.SendSMS(context.Background(), vendel.SendSMSRequest{
Recipients: []string{"+1234567890"},
Body: "Hello from Vendel!",
})
if err != nil {
panic(err)
}
fmt.Println("Batch ID:", resp.BatchID)
} Send SMS
Send to one or more recipients in E.164 format. Optionally specify a device_id to
route through a particular device.
Python
response = client.send_sms(
recipients=["+1234567890", "+0987654321"],
body="Your order has shipped!",
device_id="optional_device_id",
)
print(f"Batch: {response.batch_id}, Messages: {response.message_ids}") JavaScript / TypeScript
const response = await client.sendSms(
["+1234567890", "+0987654321"],
"Your order has shipped!",
"optional_device_id",
);
console.log(`Batch: ${response.batch_id}, Messages: ${response.message_ids}`); Go
resp, err := client.SendSMS(ctx, vendel.SendSMSRequest{
Recipients: []string{"+1234567890", "+0987654321"},
Body: "Your order has shipped!",
DeviceID: "optional_device_id",
})
fmt.Printf("Batch: %s, Messages: %v\n", resp.BatchID, resp.MessageIDs) Get quota
Check your current plan limits and usage.
Python
quota = client.get_quota()
print(f"Plan: {quota.plan}")
print(f"SMS: {quota.sms_sent_this_month}/{quota.max_sms_per_month}")
print(f"Devices: {quota.devices_registered}/{quota.max_devices}")
print(f"Resets: {quota.reset_date}") JavaScript / TypeScript
const quota = await client.getQuota();
console.log(`Plan: ${quota.plan}`);
console.log(`SMS: ${quota.sms_sent_this_month}/${quota.max_sms_per_month}`);
console.log(`Devices: ${quota.devices_registered}/${quota.max_devices}`);
console.log(`Resets: ${quota.reset_date}`); Go
quota, err := client.GetQuota(ctx)
fmt.Printf("Plan: %s\n", quota.Plan)
fmt.Printf("SMS: %d/%d\n", quota.SMSSentThisMonth, quota.MaxSMSPerMonth)
fmt.Printf("Devices: %d/%d\n", quota.DevicesRegistered, quota.MaxDevices)
fmt.Printf("Resets: %s\n", quota.ResetDate) Webhook verification
When you receive a webhook, verify the X-Webhook-Signature header to ensure
it came from Vendel. The signature is an HMAC-SHA256 hex digest of the request body.
Python (Flask)
from vendel_sdk import verify_webhook_signature
@app.route("/webhook", methods=["POST"])
def webhook():
signature = request.headers.get("X-Webhook-Signature", "")
is_valid = verify_webhook_signature(
payload=request.get_data(as_text=True),
signature=signature,
secret="your_webhook_secret",
)
if not is_valid:
return "Invalid signature", 401
event = request.json
print(f"Event: {event['event']}")
return "OK", 200 JavaScript / TypeScript (Express)
import { verifyWebhookSignature } from "vendel-sdk";
import express from "express";
const app = express();
app.use(express.raw({ type: "application/json" }));
app.post("/webhook", (req, res) => {
const signature = req.headers["x-webhook-signature"] as string;
const isValid = verifyWebhookSignature(
req.body.toString(),
signature,
"your_webhook_secret",
);
if (!isValid) return res.status(401).send("Invalid signature");
const event = JSON.parse(req.body.toString());
console.log("Event:", event.event);
res.sendStatus(200);
}); Go (net/http)
import (
"io"
"net/http"
vendel "github.com/JimScope/vendel-sdk-go"
)
func webhookHandler(w http.ResponseWriter, r *http.Request) {
body, _ := io.ReadAll(r.Body)
signature := r.Header.Get("X-Webhook-Signature")
if !vendel.VerifyWebhookSignature(string(body), signature, "your_webhook_secret") {
http.Error(w, "Invalid signature", http.StatusUnauthorized)
return
}
// Process the event...
w.WriteHeader(http.StatusOK)
} Error handling
All SDKs throw typed errors. Quota errors (HTTP 429) include limit, used,
and available fields so you can show meaningful messages to users.
Python
from vendel_sdk import VendelClient, VendelAPIError, VendelQuotaError
try:
client.send_sms(["+1234567890"], "Hello")
except VendelQuotaError as e:
print(f"Quota exceeded: {e.used}/{e.limit} used, {e.available} remaining")
except VendelAPIError as e:
print(f"API error [{e.status_code}]: {e.message}") JavaScript / TypeScript
import { VendelClient, VendelQuotaError, VendelAPIError } from "vendel-sdk";
try {
await client.sendSms(["+1234567890"], "Hello");
} catch (e) {
if (e instanceof VendelQuotaError) {
console.log(`Quota exceeded: ${e.used}/${e.limit} used, ${e.available} remaining`);
} else if (e instanceof VendelAPIError) {
console.log(`API error [${e.statusCode}]: ${e.message}`);
}
} Go
resp, err := client.SendSMS(ctx, req)
if err != nil {
if vendel.IsQuotaError(err) {
qe := err.(*vendel.QuotaError)
fmt.Printf("Quota exceeded: %d/%d used, %d remaining\n", qe.Used, qe.Limit, qe.Available)
} else if vendel.IsAPIError(err) {
ae := err.(*vendel.VendelError)
fmt.Printf("API error [%d]: %s\n", ae.StatusCode, ae.Message)
} else {
fmt.Printf("Network error: %v\n", err)
}
}