Example Flows
Copy-paste curl walkthroughs for common use cases.
Replace placeholders:
$WALLIN_URL— your Wallin domain (e.g., https://app.wallin.example)$TOKEN— Sanctum token from login$OTP_KEY— OTP API key from/otp-applications
Flow 1: OTP Send & Verify
User requests a verification code, you send via WhatsApp, they verify.
#!/bin/bash
WALLIN_URL="https://app.wallin.example"
OTP_KEY="your_otp_key_here"
PHONE="+201001234567"
echo "=== Step 1: Send OTP ==="
RESPONSE=$(curl -s -X POST "$WALLIN_URL/api/v1/otp/send" \
-H "X-Wallin-OTP-Key: $OTP_KEY" \
-H "Content-Type: application/json" \
-d "{\"phone_number\": \"$PHONE\"}")
echo "Response: $RESPONSE"
# Extract reference_id for later verification
REFERENCE=$(echo $RESPONSE | jq -r '.data.reference_id')
EXPIRES=$(echo $RESPONSE | jq -r '.data.expires_at')
echo "Reference ID: $REFERENCE"
echo "Expires at: $EXPIRES"
echo ""
echo "=== User receives OTP on WhatsApp ==="
echo "(Simulated code in test mode: usually 000000 or check logs)"
echo ""
echo "=== Step 2: User enters code (e.g., 123456) ==="
CODE="123456"
VERIFY=$(curl -s -X POST "$WALLIN_URL/api/v1/otp/verify" \
-H "X-Wallin-OTP-Key: $OTP_KEY" \
-H "Content-Type: application/json" \
-d "{\"reference_id\": \"$REFERENCE\", \"code\": \"$CODE\"}")
echo "Verification response: $VERIFY"
VERIFIED=$(echo $VERIFY | jq -r '.data.verified')
if [ "$VERIFIED" = "true" ]; then
echo "✓ OTP verified! User authenticated."
else
echo "✗ OTP verification failed."
REMAINING=$(echo $VERIFY | jq -r '.data.attempts_remaining')
echo "Attempts remaining: $REMAINING"
fi
echo ""
echo "=== Step 3 (optional): Resend if user requests ==="
RESEND=$(curl -s -X POST "$WALLIN_URL/api/v1/otp/resend" \
-H "X-Wallin-OTP-Key: $OTP_KEY" \
-H "Content-Type: application/json" \
-d "{\"reference_id\": \"$REFERENCE\"}")
NEW_EXPIRES=$(echo $RESEND | jq -r '.data.expires_at')
echo "New expiry: $NEW_EXPIRES"
Flow 2: Agent Bot (Automated Replies)
Log in as an agent, list conversations, send a reply, resolve.
#!/bin/bash
WALLIN_URL="https://app.wallin.example"
EMAIL="agent@example.com"
PASSWORD="agent_password"
echo "=== Step 1: Agent Login ==="
LOGIN=$(curl -s -X POST "$WALLIN_URL/api/agent/login" \
-H "Content-Type: application/json" \
-d "{\"email\": \"$EMAIL\", \"password\": \"$PASSWORD\", \"device_name\": \"bot\"}")
TOKEN=$(echo $LOGIN | jq -r '.token')
AGENT_ID=$(echo $LOGIN | jq -r '.user.id')
echo "Token: $TOKEN"
echo "Agent ID: $AGENT_ID"
echo ""
echo "=== Step 2: List Active Conversations ==="
CONVS=$(curl -s -X GET "$WALLIN_URL/api/agent/conversations?status=active&per_page=5" \
-H "Authorization: Bearer $TOKEN")
echo "Conversations: $(echo $CONVS | jq '.data | length') found"
echo $CONVS | jq '.data[] | {id, customer_name, status, channel}'
# Pick the first conversation
CONV_ID=$(echo $CONVS | jq -r '.data[0].id')
echo ""
echo "Selected conversation ID: $CONV_ID"
echo ""
echo "=== Step 3: Send a Reply ==="
REPLY=$(curl -s -X POST "$WALLIN_URL/api/agent/conversations/$CONV_ID/messages/text" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"message": "Thank you for contacting us! We will get back to you shortly."}')
echo "Reply sent: $(echo $REPLY | jq -r '.success')"
echo ""
echo "=== Step 4: Add Label ==="
LABEL=$(curl -s -X POST "$WALLIN_URL/api/agent/conversations/$CONV_ID/labels" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"slug": "inquiry"}')
echo "Label added: $(echo $LABEL | jq -r '.success')"
echo ""
echo "=== Step 5: Resolve Conversation ==="
RESOLVE=$(curl -s -X POST "$WALLIN_URL/api/agent/conversations/$CONV_ID/resolve" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"notes": "Sent auto-response, marking resolved."}')
echo "Resolved: $(echo $RESOLVE | jq -r '.success')"
Flow 3: Send WhatsApp Template via API
Send a pre-approved template to a customer (requires Sanctum token).
#!/bin/bash
WALLIN_URL="https://app.wallin.example"
TOKEN="your_sanctum_token"
WABA_ID=1 # WhatsApp Business Account ID
RECIPIENT="+201001234567"
TEMPLATE_NAME="hello_world"
TEMPLATE_LANG="en"
echo "=== Send WhatsApp Template ==="
SEND=$(curl -s -X POST "$WALLIN_URL/api/whatsapp/send-template" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"business_account_id\": $WABA_ID,
\"to\": \"$RECIPIENT\",
\"template_name\": \"$TEMPLATE_NAME\",
\"language_code\": \"$TEMPLATE_LANG\",
\"parameters\": [\"Ahmad\", \"2024-07-19\"]
}")
echo "Response:"
echo $SEND | jq .
SUCCESS=$(echo $SEND | jq -r '.success')
if [ "$SUCCESS" = "true" ]; then
MSG_ID=$(echo $SEND | jq -r '.message_id')
WA_ID=$(echo $SEND | jq -r '.whatsapp_message_id')
echo "✓ Message sent!"
echo " Local ID: $MSG_ID"
echo " WhatsApp ID: $WA_ID"
else
echo "✗ Send failed"
echo $SEND | jq '.error'
fi
Flow 4: Custom Integration (Event Webhook)
Set up a webhook to trigger custom logic when messages arrive.
Example: Auto-assign to supervisor if label contains "urgent"
# Flask endpoint (your server)
from flask import Flask, request
import hmac
import hashlib
import json
app = Flask(__name__)
WALLIN_WEBHOOK_SECRET = "your_webhook_secret"
@app.route('/webhook/wallin', methods=['POST'])
def wallin_webhook():
# Verify signature
payload = request.get_data()
signature = request.headers.get('X-Wallin-Signature')
expected_sig = hmac.new(
WALLIN_WEBHOOK_SECRET.encode(),
payload,
hashlib.sha256
).hexdigest()
if not hmac.compare_digest(signature, expected_sig):
return {'error': 'Invalid signature'}, 403
event = request.json
# Handle message.received event
if event.get('type') == 'message.received':
message = event['data']['message']
conversation_id = event['data']['conversation_id']
# Check if message contains "urgent"
if 'urgent' in message.get('content', {}).get('text', '').lower():
# Call Wallin API to assign to supervisor
supervisor_id = 42
requests.post(
f'https://wallin.example/api/agent/conversations/{conversation_id}/assign',
headers={'Authorization': f'Bearer {api_token}'},
json={'agent_id': supervisor_id}
)
return {'status': 'ok'}, 200
if __name__ == '__main__':
app.run(port=5000)
Configure webhook at /channels/{connectionId} → Webhooks → URL: https://your-domain.com/webhook/wallin
Flow 5: Bulk Agent Assignment
Assign multiple conversations to an agent at once.
#!/bin/bash
WALLIN_URL="https://app.wallin.example"
TOKEN="your_sanctum_token"
AGENT_ID=5 # Target agent
echo "=== List Pending Conversations ==="
CONVS=$(curl -s -X GET "$WALLIN_URL/api/agent/conversations?status=pending&per_page=100" \
-H "Authorization: Bearer $TOKEN")
# Extract IDs
CONV_IDS=($(echo $CONVS | jq -r '.data[].id'))
echo "Found ${#CONV_IDS[@]} pending conversations"
echo ""
echo "=== Bulk Assign to Agent $AGENT_ID ==="
for CONV_ID in "${CONV_IDS[@]}"; do
echo -n "Assigning conversation $CONV_ID... "
RESULT=$(curl -s -X POST "$WALLIN_URL/api/agent/conversations/$CONV_ID/assign" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"agent_id\": $AGENT_ID}")
if [ "$(echo $RESULT | jq -r '.success')" = "true" ]; then
echo "✓"
else
echo "✗"
fi
# Rate limit: small delay between requests
sleep 0.1
done
echo "Done!"
Flow 6: Monitor Conversation Status
Poll conversation status periodically (fallback if WebSocket unavailable).
#!/bin/bash
WALLIN_URL="https://app.wallin.example"
TOKEN="your_sanctum_token"
CONV_ID=42
POLL_INTERVAL=5 # seconds
echo "=== Poll Conversation for Updates ==="
while true; do
CONV=$(curl -s -X GET "$WALLIN_URL/api/agent/conversations/$CONV_ID" \
-H "Authorization: Bearer $TOKEN")
STATUS=$(echo $CONV | jq -r '.data.status')
UNREAD=$(echo $CONV | jq -r '.data.unread_count')
LAST_MSG=$(echo $CONV | jq -r '.data.last_message_at')
echo "[$(date '+%H:%M:%S')] Status: $STATUS | Unread: $UNREAD | Last: $LAST_MSG"
# Fetch new messages
MESSAGES=$(curl -s -X GET "$WALLIN_URL/api/agent/conversations/$CONV_ID/messages?per_page=5" \
-H "Authorization: Bearer $TOKEN")
NEW_MSG_COUNT=$(echo $MESSAGES | jq '.data | length')
if [ $NEW_MSG_COUNT -gt 0 ]; then
echo " New messages: $NEW_MSG_COUNT"
echo $MESSAGES | jq '.data[0] | {content, created_at}'
fi
# Exit if resolved
if [ "$STATUS" = "resolved" ]; then
echo "Conversation resolved. Exiting."
break
fi
sleep $POLL_INTERVAL
done
Troubleshooting Examples
"OTP rate limit exceeded"
# Wait 1 hour
sleep 3600
# Or try a different phone number
PHONE_2="+201009876543"
curl -X POST "$WALLIN_URL/api/v1/otp/send" \
-H "X-Wallin-OTP-Key: $OTP_KEY" \
-H "Content-Type: application/json" \
-d "{\"phone_number\": \"$PHONE_2\"}"
"WhatsApp message window closed"
# Use a template instead (if template supports it)
curl -X POST "$WALLIN_URL/api/whatsapp/send-template" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"business_account_id\": 1,
\"to\": \"$RECIPIENT\",
\"template_name\": \"marketing_template\",
\"language_code\": \"en\"
}"
"Invalid API key" (OTP)
# Verify key at /otp-applications
# Regenerate if needed, then retry:
OTP_KEY="newly_generated_key"
curl -X POST "$WALLIN_URL/api/v1/otp/send" \
-H "X-Wallin-OTP-Key: $OTP_KEY" \
-H "Content-Type: application/json" \
-d "{\"phone_number\": \"$PHONE\"}"
Was this page helpful?