Skip to content
5 min read

Testing & Sandbox

Develop and test without affecting production or using real WhatsApp/OTP credits.

Simulation Mode

Set WHATSAPP_SIMULATE_API=true in your .env file to enable simulation mode.

In simulation mode:

  • WhatsApp API calls are mocked — requests succeed but no actual messages are sent to WhatsApp or the customer
  • OTP API calls are mocked — OTPs are generated and tracked, but no SMS is sent via WhatsApp
  • Responses are realistic — You get the same response format as production, enabling testing without side effects

Enabling Simulation Locally

# .env (local development)
WHATSAPP_SIMULATE_API=true

Then:

# Test WhatsApp send
curl -X POST http://localhost:8003/api/whatsapp/send-text \
  -H "Authorization: Bearer token" \
  -H "Content-Type: application/json" \
  -d '{
    "business_account_id": 1,
    "to": "+201001234567",
    "message": "Test message"
  }'

# Returns simulated success (no actual send to WhatsApp)
{
  "success": true,
  "message_id": 1,
  "whatsapp_message_id": "sim_abc123"
}

Testing OTP Locally

Send Test OTP

curl -X POST http://localhost:8003/api/v1/otp/send \
  -H "X-Wallin-OTP-Key: test_key" \
  -H "Content-Type: application/json" \
  -d '{"phone_number": "+201001234567"}'

With simulation mode, the OTP is generated but not actually sent. You can see generated codes in logs or the database.

Verify Test OTP

To verify, you need to know the generated code. In simulation/test mode:

# Extract the code from the database or logs
SELECT code_hash, attempts FROM otp_requests WHERE reference_id = '...';

# Then verify (codes are usually "000000" in test mode or check logs)
curl -X POST http://localhost:8003/api/v1/otp/verify \
  -H "X-Wallin-OTP-Key: test_key" \
  -H "Content-Type: application/json" \
  -d '{"reference_id": "550e8400...", "code": "000000"}'

Webhook Testing (Local)

Verify Webhook Signature

Wallin signs incoming webhooks with X-Wallin-Signature (HMAC-SHA256 of the request body using your connection's secret key).

To test locally:

  1. Get your connection's webhook secret at /channels/{connectionId} → Webhooks

  2. Sign a test payload:

    PAYLOAD='{"object":"whatsapp_business_account","entry":[...]}'
    SECRET='your_webhook_secret'
    SIGNATURE=$(echo -n "$PAYLOAD" | openssl dgst -sha256 -mac HMAC -macopt key="$SECRET" | cut -d' ' -f2)
    
  3. Send to your local webhook endpoint:

    curl -X POST http://localhost:8003/api/whatsapp/webhook \
      -H "X-Wallin-Signature: $SIGNATURE" \
      -H "Content-Type: application/json" \
      -d "$PAYLOAD"
    

Using ngrok for Testing Webhooks

To receive actual Meta webhooks on your local machine:

  1. Install ngrok: brew install ngrok (or download)
  2. Start ngrok: ngrok http 8003
  3. Copy the forwarding URL (e.g., https://abc123.ngrok.io)
  4. In your Meta App Dashboard, set Webhook URL to: https://abc123.ngrok.io/api/whatsapp/webhook
  5. Verify token is configured in Wallin settings
  6. Test webhook from Meta dashboard → Test Webhook

ngrok forwards HTTPS traffic to your local HTTP server.

Local Development Setup

Prerequisites

# Docker-based (Sail)
./vendor/bin/sail up -d

# Database
./vendor/bin/sail artisan migrate
./vendor/bin/sail artisan db:seed (optional)

# Create a test user/agent
./vendor/bin/sail artisan tinker
# Then in Tinker:
# User::factory()->create(['email' => 'agent@test.com', 'password' => bcrypt('password')]);

Testing Endpoints

# 1. Login (get token)
TOKEN=$(curl -s -X POST http://localhost:8003/api/agent/login \
  -H "Content-Type: application/json" \
  -d '{"email":"agent@test.com","password":"password","device_name":"test"}' \
  | jq -r '.token')

echo "Token: $TOKEN"

# 2. Test Agent API
curl -X GET http://localhost:8003/api/agent/conversations \
  -H "Authorization: Bearer $TOKEN"

# 3. Test WhatsApp API (simulation)
curl -X POST http://localhost:8003/api/whatsapp/send-text \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"business_account_id":1,"to":"+201001234567","message":"Test"}'

Database Reset

After testing, reset your database to a clean state:

# Reset and re-seed
./vendor/bin/sail artisan migrate:refresh --seed

# Or drop all tables and re-migrate
./vendor/bin/sail artisan migrate:fresh

Log Inspection

View API logs during testing:

# Watch logs in real-time
./vendor/bin/sail tail -f

# Or view specific file
./vendor/bin/sail tail storage/logs/laravel.log

Look for:

  • Request/response pairs
  • Webhook processing
  • API errors

Testing Best Practices

  1. Use simulation mode for WhatsApp/OTP development
  2. Test in isolation — verify each API separately
  3. Use fixtures/factories for consistent test data
  4. Log everything — save request/response for debugging
  5. Test error cases — invalid input, rate limits, auth failures
  6. Use Postman/Insomnia for manual API exploration

Example Postman flow:

1. POST /api/agent/login → save {{token}}
2. GET /api/agent/conversations → list conversations
3. GET /api/agent/conversations/1 → get one conversation
4. POST /api/agent/conversations/1/messages/text → send message
5. GET /api/agent/conversations/1/messages → view messages

CI/CD Testing

For automated tests, use simulation mode in your CI pipeline:

# .github/workflows/test.yml
env:
  WHATSAPP_SIMULATE_API: true
  DB_DATABASE: testing

script:
  - ./vendor/bin/sail artisan test

This runs tests against a simulated WhatsApp API, avoiding external dependencies and reducing test time.

Debugging API Calls

Using curl -v

curl -v -X POST http://localhost:8003/api/agent/login \
  -H "Content-Type: application/json" \
  -d '{"email":"agent@test.com","password":"password","device_name":"test"}'

# Shows:
# > request headers
# < response headers
# < response body

Using jq for JSON Parsing

# Pretty-print JSON
curl -s http://... | jq .

# Extract specific field
curl -s http://... | jq '.token'

# Conditional filter
curl -s http://... | jq '.data[] | select(.status == "active")'

Timing Requests

time curl -X GET http://localhost:8003/api/agent/conversations \
  -H "Authorization: Bearer $TOKEN"

# Shows request duration
Was this page helpful?

See Wallin on your own channels.

Book a walkthrough — we'll connect a test account and show you the inbox, broadcasts, and automation live.