Skip to content
Nofy by Encipher Docs

SDKs

Python SDK

One client for every endpoint. Tokens, idempotency keys and error types are handled for you.

The ens_sdk package wraps the API in one client: OAuth tokens, idempotency keys and clear errors are handled inside, so your code sends notifications instead of HTTP requests.

  1. Install

    Terminal
    pip install ens_sdk
    
  2. Configure

    Credentials and tenant come from the environment, or from constructor arguments, which take precedence:

    Terminal
    ENS_SERVER_URL=https://nofy.encipher.co.tz
    ENS_CLIENT_ID=<oauth application client id>
    ENS_CLIENT_SECRET=<oauth application client secret>
    ENS_TENANT=<carrier tenant external id>
    ENS_TIMEOUT=10
    
    Python
    from ens_sdk import ENS
    
    ens = ENS()  # reads the environment above
    # or: ENS(server_url=..., client_id=..., client_secret=..., tenant=...)
    

    Tokens are minted with client credentials and cached until they expire. Calls without configuration raise ENSRefused straight away instead of failing obscurely later.

  3. Send

    Python
    ens.send_email("ops@acme.co.tz", "Shift closed", "Shift 7 closed.")
    ens.send_whatsapp_template("+255700000000", "otp_login", "en", ["482916"])
    ens.send_sms("+255700000000", "Your code is 482916")
    ens.send_push("user-uuid-1", "Shift closed", "Tap for the summary.")
    

Email and WhatsApp accept html and inline_images (email), callback_url, event_type, reference and idempotency_key. These default to sensible unique values when omitted, so plain calls are already retry-safe. Push needs a tenant and addresses your user ids, so register devices first.

send_sms uses the legacy path

send_sms posts to /v1/notification/send/, which sends exactly like the carrier channel but skips idempotency keys, and attributes quotas to a tenant only when you pass tenant=. New SMS integrations that need those guarantees should call POST /v2/messages directly (see Sending on v2). The Quickstart shows the same send in Node.js, PHP, Go, Rust and cURL.

Devices & tenants

Python
ens.register_device("user-uuid-1", "fcm-device-token", platform="android")
ens.deregister_device(external_user_id="user-uuid-1")  # logout: whole fleet
ens.provision_tenant("company-uuid-1", name="Acme Fuel")  # idempotent

Errors

Exception Meaning
ENSRefused Not configured, missing tenant for the call, or the service answered 400.
ENSQuotaExceeded Daily quota reached (429). Back off until tomorrow.
ENSUnreachable Network fault or unexpected status. Safe to retry.

All three subclass ENSError, so one except ENSError covers the client.

Esc
↑↓ to move↵ to open