Vesper Relay

API

Base URL https://relay.vesperai.ch/api/v1. Every request carries Authorization: Bearer <api key> from Settings.

Send a template message

POST /api/v1/messages
{"to": "+41 79 123 45 67", "template": "termin_bestaetigung", "language": "de",
 "params": ["Max", "Dienstag, 14.10.2026", "09:00", "Haarschnitt"]}

202 {"id": 17, "wa_message_id": "wamid.…", "status": "accepted", …}

Numbers without a country code are read in default_region (default CH). The response status is Meta's acceptance; sent, delivered, read or failed follow by webhook and on GET /api/v1/messages/{id}.

Free text

POST /api/v1/messages
{"to": "+41791234567", "text": "Thanks, see you tomorrow."}

Only delivered inside the 24-hour window after the customer wrote last. Outside it, use a template.

Templates

GET  /api/v1/templates
POST /api/v1/templates
{"name": "termin_erinnerung", "language": "de", "category": "UTILITY",
 "body": "Hallo {{1}}, Erinnerung: {{2}} um {{3}} Uhr.", "examples": ["Max", "Dienstag", "09:00"]}

Meta reviews every template, usually within minutes. Variables are {{1}}, {{2}}, … without gaps; give one example per variable.

Numbers

GET /api/v1/numbers

Your webhook

Set an https URL in Settings. Every Meta event for your numbers is forwarded as-is (Meta's own JSON shape) with header X-Relay-Signature-256: sha256=HMAC-SHA256(webhook secret, raw body). Answer 2xx within 8 seconds. Delivery statuses, incoming messages and template status updates all arrive this way.

Errors

401 bad key · 409 no number connected · 422 validation · 502 Meta rejected the call, body carries Meta's message.