Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

1 Commit

Repository files navigation

engagelab-otp · Python

Official Python SDK for EngageLab OTP.
Zero dependencies. Python 3.8+.

Install

pip install engagelab-otp

Quick start

importosfromengagelab_otpimportOTPClientotp=OTPClient(
os.environ["ENGAGELAB_DEV_KEY"],
os.environ["ENGAGELAB_DEV_SECRET"],
)
# Platform-generated OTP — easiest pathresult=otp.send("+6591234567", "your-template-id", {"name": "Alice"}, language="en")
check=otp.verify(result["message_id"], user_typed_code)
ifcheck["verified"]:
...

Two send modes

ModeMethodWhen to use
Platform-generatedotp.send()EngageLab generates and stores the code. You only call verify() later.
Caller-generatedotp.send_custom()You generate the code yourself. EngageLab is just the carrier.
# Platform-generatedr=otp.send("+6591234567", "tpl-id", {"name": "Alice"}, language="en")
v=otp.verify(r["message_id"], "123456")
# Caller-generatedotp.send_custom("+6591234567", "custom-tpl", {"code": "482910", "name": "Alice"})

Webhook callbacks

EngageLab signs callbacks with X-CALLBACK-ID (HMAC-SHA256). The SDK verifies signatures and parses events for you.

Whitelist source IPs in your firewall: 119.8.170.74, 114.119.180.30

fromflaskimportFlaskfromengagelab_otpimportWebhookVerifier, MessageStatusEventapp=Flask(__name__)
verifier=WebhookVerifier(
username=os.environ["ENGAGELAB_WEBHOOK_USERNAME"],
secret=os.environ["ENGAGELAB_WEBHOOK_SECRET"],
)
defhandle(events):
foreinevents:
ifnotisinstance(e, MessageStatusEvent):
continueifnote.is_terminal:
continue# mid-flight, waitife.status=="delivered":
mark_delivered(e.message_id)
elife.status=="verified":
mark_verified(e.message_id)
app.add_url_rule(
"/webhook",
"engagelab_webhook",
verifier.flask_view(handle),
methods=["POST"],
)

Event types

parse_events() returns instances of four dataclasses:

ClassWhenKey fields
MessageStatusEventper-message lifecyclemessage_id, status, is_terminal, current_send_channel, error_code
NotificationEventaccount-level alertevent, data
UplinkEventinbound user replydata["from"], data["body"]
SystemEventconsole action auditevent, data

Message status enum

plan · target_valid · target_invalid
sent · sent_failed
delivered · delivered_failed
verified · verified_failed · verified_timeout

is_terminal == True for: delivered, delivered_failed, sent_failed, verified*, target_invalid.

Error handling

fromengagelab_otpimportEngagelabErrortry:
otp.send("+6591234567", "tpl", {})
exceptEngagelabErrorase:
ife.retryable:
# HTTP 429/5xx, or API codes 1000/5001/5016# → exponential backoff
...
else:
# Permanent failure — fix call or notify userprint(e.code, e.http_status, str(e))

Examples

See examples/ for runnable code:

  • 01_send_and_verify.py — platform-generated OTP, full flow
  • 02_send_custom.py — caller-generated code, single + bulk
  • 03_webhook_flask.py — receive callbacks via Flask
  • 04_error_handling.py — retry strategy and error categorization

Run tests

python tests/test_sdk.py

License

MIT

About

engagelab otp python sdk

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages