Skicka och ta emot SMS via SMS-servern. Du autentiserar varje anrop med din
API-nyckel i headern X-API-Key. Nyckeln (och din
webhook_secret för att verifiera inkommande anrop) fÄr du av administratören.
Bas-URL: https://utskick.karlberg.nu
1. Skicka SMS
POST /api/send â ett SMS direkt
Skickar omedelbart och svarar nÀr SMS:et Àr skickat (eller misslyckats).
curl -s https://utskick.karlberg.nu/api/send \
-H "X-API-Key: DIN_NYCKEL" \
-H "Content-Type: application/json" \
-d '{"number":"+46701234567","message":"Hej frÄn oss!"}'
# Svar:
# {"id": 42, "status": "sent", "router_ip": "10.0.0.3", "attempts": 1}
POST /api/send-bulk â flera mottagare
Köas och skickas med jÀmna, oregelbundna mellanrum (skonsamt mot operatören). Du fÄr
ett id per meddelande â leveransstatus kommer via webhook eller pollning.
curl -s https://utskick.karlberg.nu/api/send-bulk \
-H "X-API-Key: DIN_NYCKEL" \
-H "Content-Type: application/json" \
-d '{"numbers":["+46701234567","+46707654321"],"message":"Kampanjtext"}'
# Svar:
# {"ids":[43,44], "count":2, "status":"queued", "queue":2}
Valfria fÀlt (bÄda endpoints)
Servern klÀr normalt meddelandet med en varierad hÀlsning + ditt tjÀnstnamn, och
skriver om kod-meddelanden till OTP xxxx-format (sÄ mobilen kÀnner
igen engÄngskoden). Du kan styra detta:
"raw": trueâ skicka texten exakt som den Ă€r, ingen omskrivning."service": "Mitt Företag"â avsĂ€ndarnamnet i hĂ€lsningen (annars hĂ€rleds det frĂ„n din nyckel)."name": "Johnny"â mottagarens namn för personlig hĂ€lsning ("Hej Johnny! âŠ"), endast/api/send.
2. Ta emot leveransrapporter och svar (webhook)
Ge administratören en webhook-URL (din egen endpoint). Dit POST:ar SMS-servern tvÄ sorters hÀndelser, som JSON, signerade sÄ att du kan verifiera att de kommer frÄn oss. Du behöver alltsÄ bygga en mottagande endpoint pÄ din sida.
Leveransrapport
POST:as nÀr ett av dina utskick nÄr slutstatus (sent eller failed).
{
"type": "delivery_report",
"id": 43,
"number": "+46701234567",
"status": "sent", // sent | failed
"router_ip": "10.0.0.3",
"attempts": 1,
"error": null
}
Inkommande svar
NÀr nÄgon svarar pÄ ett SMS du skickat POST:as svaret till dig (svaret kopplas till dig eftersom du var den som senast skrev till numret).
{
"type": "inbound_sms",
"id": 87,
"from": "+46701234567",
"message": "Ja tack!",
"date": "2026-06-04 21:15:00"
}
Verifiera signaturen
Varje webhook-anrop har headern X-SMS-Signature =
base64(HMAC_SHA256(rÄ_body, webhook_secret)). RÀkna ut samma vÀrde pÄ din
sida och jÀmför. Verifiera mot den rÄa bodyn (inte en om-serialiserad JSON).
Node.js (Express):
const crypto = require("crypto");
const SECRET = "DIN_WEBHOOK_SECRET";
// Viktigt: lĂ€s den RĂ
A bodyn â t.ex. express.raw({ type: "application/json" })
app.post("/sms-webhook", express.raw({ type: "*/*" }), (req, res) => {
const sig = crypto.createHmac("sha256", SECRET).update(req.body).digest("base64");
if (sig !== req.get("X-SMS-Signature")) return res.sendStatus(401);
const event = JSON.parse(req.body.toString());
if (event.type === "delivery_report") { /* ... */ }
if (event.type === "inbound_sms") { /* ... svara kunden via /api/send ... */ }
res.sendStatus(200);
});
Python (Flask):
import base64, hashlib, hmac
from flask import Flask, request, abort
SECRET = b"DIN_WEBHOOK_SECRET"
app = Flask(__name__)
@app.post("/sms-webhook")
def hook():
raw = request.get_data() # rÄ body
sig = base64.b64encode(hmac.new(SECRET, raw, hashlib.sha256).digest()).decode()
if not hmac.compare_digest(sig, request.headers.get("X-SMS-Signature", "")):
abort(401)
event = request.get_json()
# event["type"] == "delivery_report" | "inbound_sms"
return "", 200
inbound_sms genom att helt enkelt skicka ett nytt /api/send
till samma from-nummer. DÄ fortsÀtter trÄden och nÀsta svar kommer
tillbaka till dig igen.3. HĂ€mta status utan webhook (pollning)
Vill du inte bygga en webhook kan du i stÀllet hÀmta lÀget med din nyckel:
| Endpoint | Beskrivning |
|---|---|
GET /api/my/info | Din nyckels uppgifter, antal skickade och din webhook_secret. |
GET /api/my/messages?limit=50 | Dina utgÄende SMS med leveransstatus (sent/failed/pending). |
GET /api/my/received?limit=50 | Inkommande svar kopplade till dig. |
curl -s "https://utskick.karlberg.nu/api/my/messages?limit=20" -H "X-API-Key: DIN_NYCKEL"
Fel & grÀnser
| Kod | Betyder |
|---|---|
401 | Saknad/ogiltig/inaktiverad API-nyckel. |
402 | MĂ„nadskvoten för din nyckel Ă€r nĂ„dd â kontakta administratören. |
429 | HastighetsgrĂ€ns nĂ„dd (för mĂ„nga SMS per minut) â vĂ€nta och försök igen. |
503 | Inga routrar online just nu â försök igen senare. |
502 | Utskicket misslyckades pÄ alla routrar. |
Din nyckels pris/SMS, ev. mÄnadstak och förbrukning denna mÄnad ser du via
GET /api/my/info (fÀlten price_ore, monthly_cap,
month_count, month_cost_ore).
Externa nycklar fĂ„r bara skicka och hĂ€mta sina egna data â inte se andras utskick, kontakter eller dashboarden.