Skip to content

Repository files navigation

safwatech-otp

Official Python SDK for the Safwatech OTP / verification platform — OTP (push / SMS / email / WhatsApp), TOTP authenticator (RFC 6238) with backup codes, magic links, silent push approval, and WebAuthn / passkeys.

pip install safwatech-otp

Requires Python ≥ 3.9. Single runtime dependency: requests.

Quick start

from safwatech_otp import OTPClient

client = OTPClient(
    api_key="sk_test_…",                       # or sk_live_…
    base_url="https://otp.safwatech.com.ly",
)

sent = client.send_otp("+218911234567", channel="sms", reference_id="order-42")
# When using a sandbox key, the response includes the otp_code so you can
# round-trip without hitting a real SMS provider:
if code := sent["result"].get("otp_code"):
    client.verify_otp("+218911234567", code, reference_id="order-42")

API keys are issued from the client portal. sk_test_* keys put the call in sandbox mode — no real delivery, no quota consumption, responses are stamped with X-Sandbox: true.

Response envelope

All endpoints return a JSON envelope; OTPClient returns the decoded body verbatim so you can read the platform's payload structure directly:

{
  "status": "success",
  "result": {...}             # endpoint-specific
}

Errors raise OTPClientError with the HTTP status, decoded payload, and the Retry-After value when present:

from safwatech_otp import OTPClientError

try:
    client.send_otp("+218911234567")
except OTPClientError as exc:
    if exc.status == 429:
        time.sleep(exc.retry_after or 1)
        ...

Methods

Surface Methods
OTP send_otp · verify_otp · get_status · usage
Scheduled schedule_otp · cancel_scheduled · list_scheduled
TOTP enroll_totp · verify_totp · totp_status · unenroll_totp · generate_backup_codes
Magic links send_magic_link · get_magic_link · cancel_magic_link · wait_for_magic_link
Silent push auth request_auth · get_auth_request · cancel_auth_request · wait_for_auth
WebAuthn / passkeys webauthn_register · webauthn_authenticate · get_webauthn · cancel_webauthn · wait_for_webauthn

The wait_for_* helpers poll the matching get_* endpoint until the request reaches a terminal state (e.g. consumed | expired | cancelled for magic links) or the timeout elapses; they return the final polled response.

Verifying webhooks

from safwatech_otp import verify_webhook

if not verify_webhook(
    raw_body=request.body,
    secret="the callback_secret you set on your service",
    signature_header=request.headers.get("X-Webhook-Signature", ""),
    timestamp_header=request.headers.get("X-Webhook-Timestamp", ""),
):
    abort(401)

The header format is X-Webhook-Signature: v1=<hex> over "{timestamp}.{body}" (HMAC-SHA256). A 300 s tolerance window is enforced by default.

Examples & docs

  • Live API reference: https://otp.safwatech.com.ly/docs
  • Runnable scripts: sdks/examples/ in the source repo (python_example.py, magic_link.py, silent_auth.py, totp_enroll.py, webauthn.py, verify_webhook.py).

Development

pip install -e ".[test]"
pytest

License

MIT. See LICENSE.

About

Official Safwatech OTP / verification platform SDK for python

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages