Observed since 20 Oct, 18:12 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
Official Python SDK for Achek — WhatsApp OTP, AI chatbots & business messaging for Nigeria
Official Python SDK for Achek — WhatsApp OTP, automated alerts, transaction notifications, broadcasts, support ticket tracking, transactional email, and webhook utilities for Nigeria and Africa.
pip install achek
from achek import AchekConnect
client = AchekConnect(api_key="your_api_key")
# Send WhatsApp OTP
result = client.otp.send("+2348012345678")
request_id = result["requestId"]
# Verify the code the user entered
verification = client.otp.verify(request_id, user_code)
if verification["valid"]:
login_user() # ✅
Get your API key from the Achek dashboard.
# Simple send
result = client.otp.send("+2348012345678")
request_id = result["requestId"]
# With custom template (Growth+ plans)
result = client.otp.send(
"+2348012345678",
template="Hi {{name}}, your {{company}} code is {{code}}. Valid 10 mins.",
recipient_name="Emeka",
company_name="MyApp",
idempotency_key="otp-req-user-789", # safe to retry with the same key
)
# Verify
result = client.otp.verify(request_id, "847293")
# {"valid": True, "message": "OTP verified successfully"}
# Fetch OTP logs
logs = client.otp.logs(limit=20, status="verified")
Send formatted debit/credit/transfer alerts directly to a customer's WhatsApp:
client.alerts.transaction(
"+2348012345678",
type="debit",
amount=15000,
reference="TXN-20240519-001",
account_name="Emeka Okafor",
balance=240000,
description="Transfer to Kuda",
)
This automatically sends a clean WhatsApp message:
💸 Debit Alert
Amount: ₦15,000.00
Account: Emeka Okafor
Ref: `TXN-20240519-001`
Narration: Transfer to Kuda
Balance: ₦240,000.00
_Powered by Achek_
client.alerts.send(
"+2348012345678",
"*Your account has been credited with ₦5,000* 🎉",
category="notification",
idempotency_key="alert-credit-txn-001",
)
Send a single WhatsApp message to up to 1,000 recipients at once:
result = client.broadcasts.send(
name="Black Friday Promo",
message="🔥 *50% OFF* today only! Code: *FRIDAY50*",
recipients=["+2348012345678", "+2349087654321"], # up to 1000
)
# Check delivery status
status = client.broadcasts.status(result["id"])
Create support tickets and keep customers updated on WhatsApp automatically:
# Create a ticket — customer gets a WhatsApp notification
ticket = client.tickets.create(
"+2348012345678",
"Payment not reflecting",
description="Paid ₦5,000 but order not updated",
priority="high",
notify_customer=True,
)
ticket_id = ticket["ticketId"]
# Update — customer gets a WhatsApp update
client.tickets.update(
ticket_id,
status="in_progress",
notify_customer=True,
notification_message="We're investigating — expected resolution: 2 hours.",
)
# Resolve
client.tickets.resolve(ticket_id, "Your issue has been fixed! Check your account.")
# List open tickets
open_tickets = client.tickets.list(status="open")
Send transactional emails via Achek's configured SMTP. Sender address and domain are set in your dashboard.
# HTML email
client.email.send(
to="customer@example.com",
subject="Your OTP code",
html="<p>Your code is <strong>847293</strong>. Valid for 10 minutes.</p>",
)
# Plain-text email
client.email.send(
to="customer@example.com",
subject="Order confirmed",
text="Thanks for your order! Delivery in 3–5 business days.",
from_name="MyShop Support",
)
Achek includes a built-in AI chatbot that responds to WhatsApp messages automatically. Configure it from the dashboard — no extra API calls needed.
Set a webhook URL in AI Bot → Webhook URL in your dashboard. Achek will POST to it on these events:
| Event | Fired when | Key fields |
|---|---|---|
message.incoming | Customer sends a message to your bot | phone, message, timestamp |
message.outgoing | Bot replies to the customer | phone, message, timestamp |
spam.quarantine | Sender exceeded velocity limit | phone, quarantined_until, message_count |
handoff.requested | Consecutive depth reached / human took over | phone, reason, exchanges, bot_config_id |
ticket.created | Bot opens a support ticket | ticket_id, phone, subject, priority |
lead.captured | Bot saves a customer lead | ticket_id, phone, name, email |
Achek signs every delivery with HMAC-SHA256. Always verify before trusting the payload:
# Flask example
from flask import Flask, request, abort
from achek import AchekWebhookHelper
app = Flask(__name__)
helper = AchekWebhookHelper(os.environ["ACHEK_WEBHOOK_SECRET"])
@app.post("/webhook/achek")
def achek_webhook():
sig = request.headers.get("X-Achek-Signature", "")
if not helper.verify(sig, request.get_data()):
abort(400, "Invalid signature")
event = helper.parse(request.get_data())
if event["event"] == "handoff.requested":
pass # notify your support team
if event["event"] == "lead.captured":
phone = event.get("phone")
name = event.get("name")
# → sync to your CRM, spreadsheet, etc.
return "", 200
# Django example
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse, HttpResponseBadRequest
from achek import AchekWebhookHelper
helper = AchekWebhookHelper(settings.ACHEK_WEBHOOK_SECRET)
@csrf_exempt
def achek_webhook(request):
sig = request.headers.get("X-Achek-Signature", "")
if not helper.verify(sig, request.body):
return HttpResponseBadRequest("Invalid signature")
event = helper.parse(request.body)
return HttpResponse(status=200)
all_tickets = client.tickets.list(status="open")
leads = [t for t in all_tickets if t.get("metadata", {}).get("type") == "lead"]
for lead in leads:
print(lead["ticketId"]) # "LEAD-1748000000000-XY12"
print(lead["phoneNumber"]) # "+2348012345678"
print(lead["metadata"]) # { "source": "whatsapp_bot", "type": "lead", ... }
from achek import AchekConnect, AchekConnectError
try:
client.otp.send("+2348012345678")
except AchekConnectError as e:
print(e.args[0]) # "No active subscription"
print(e.status_code) # 402
print(e.code) # "SUBSCRIPTION_REQUIRED"
client = AchekConnect(
api_key="your_api_key",
base_url="https://api.achek.com.ng", # override if self-hosted
timeout=15, # seconds (default: 15)
max_attempts=3, # total tries incl. first (default: 3)
initial_delay_ms=500, # first retry: 500 ms, then 1 000, 2 000…
)
| Module | Method | Description |
|---|---|---|
otp | send(phone, **kwargs) | Send WhatsApp OTP |
otp | verify(request_id, code) | Verify OTP code |
otp | logs(**kwargs) | Fetch OTP delivery logs |
alerts | send(phone, message, **kwargs) | Send custom WhatsApp alert |
alerts | transaction(phone, **kwargs) | Send formatted transaction alert |
broadcasts | send(name, message, recipients) | Send broadcast to up to 1,000 numbers |
broadcasts | list() | List recent broadcasts |
broadcasts | status(broadcast_id) | Get broadcast delivery status |
tickets | create(phone, subject, **kwargs) | Create support ticket |
tickets | list(**kwargs) | List tickets |
tickets | get(ticket_id) | Get ticket by ID |
tickets | update(ticket_id, **kwargs) | Update status/priority |
tickets | resolve(ticket_id, message?) | Resolve and notify customer |
email | send(to, subject, **kwargs) | Send transactional email |
AchekWebhookHelper | verify(sig, payload) | Verify HMAC-SHA256 signature |
AchekWebhookHelper | parse(payload) | Parse raw webhook payload |
MIT — see LICENSE
Download counts and popularity will appear here as the collector receives them.
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 2.0.1 | 25 May 2026 | 0 |
This describes our collected data; it is not a security assessment.
Observed since 20 Oct, 18:12 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:eac827b96484add895e8ca4c1316ff1c8a8fb05662feaa4f89c06619acbf3a3d