Python
Installation
pip install httpx
Client
# notifo.py
import os
import httpx
BASE_URL = 'https://api.notifo.cloud'
API_KEY = os.environ['NOTIFO_API_KEY']
_headers = {'X-Api-Key': API_KEY, 'Content-Type': 'application/json'}
def send_text(channel: str, to: str, text: str, **kwargs) -> dict:
r = httpx.post(
f'{BASE_URL}/v1/notify/{channel}/text',
headers=_headers,
json={'to': to, 'text': text, **kwargs},
)
r.raise_for_status()
return r.json()
def send_media(channel: str, to: str, type_: str, url: str, **kwargs) -> dict:
r = httpx.post(
f'{BASE_URL}/v1/notify/{channel}/media',
headers=_headers,
json={'to': to, 'type': type_, 'url': url, **kwargs},
)
r.raise_for_status()
return r.json()
def send_bulk(channel: str, messages: list[dict]) -> list[dict]:
r = httpx.post(
f'{BASE_URL}/v1/notify/{channel}/bulk',
headers=_headers,
json={'messages': messages},
)
r.raise_for_status()
return r.json()
Usage
from notifo import send_text, send_media, send_bulk
# Text
msg = send_text('whatsapp', '+905551234567', 'Hello from Notifo!')
print(msg['id'], msg['status'])
# Image
send_media('whatsapp', '+905551234567', 'image', 'https://example.com/banner.png',
caption='New promotion!')
# Bulk
results = send_bulk('whatsapp', [
{'to': '+905551111111', 'text': 'Hi Alice'},
{'to': '+905552222222', 'text': 'Hi Bob'},
])
# Idempotent
send_text('whatsapp', '+905551234567', 'OTP: 456789',
idempotencyKey='otp-user-99-1700000000')
Webhook verification (Flask)
import hashlib, hmac, json, os
from flask import Flask, request, abort
app = Flask(__name__)
WEBHOOK_SECRET = os.environ['NOTIFO_WEBHOOK_SECRET']
@app.route('/webhooks/notifo', methods=['POST'])
def handle_webhook():
sig = request.headers.get('X-Notifo-Signature', '')
raw_body = request.get_data()
secret_hash = hashlib.sha256(WEBHOOK_SECRET.encode()).hexdigest()
expected = 'sha256=' + hmac.new(secret_hash.encode(), raw_body, hashlib.sha256).hexdigest()
if not hmac.compare_digest(sig, expected):
abort(401)
event = json.loads(raw_body)
print(f"[{event['event']}] message={event['messageId']} status={event['status']}")
return '', 200