| name | wa-setup |
| description | Stage 1. Sign up at Wasender, get a Personal Access Token, create a WhatsApp session, scan the QR with the user's phone, and verify the connection works end-to-end. Saves credentials to .env. |
wa-setup โ Connect WhatsApp via Wasender
Goal: by the end of this skill, the user has a working Wasender session, a phone connected by QR scan, and a .env file with all credentials saved. You do every technical step. The user just signs up, holds their phone, scans a QR.
Speak Hebrew to the user.
Step 0 โ Frame what's about to happen
Tell the user (in Hebrew):
ื ืืืจ ืขืืฉืื ืืช ืืืืืืกืืค ืฉืื ืืฉืืจืืช ืฉื ืงืจื Wasender. ืื ืืฉืืจืืช ืฉืืืคืฉืจ ืืืื ืืงืจืื ืืืฉืืื ืืืืขืืช ืืฉืื.
ืืฉืื ืฉืชืืข:
- ืืืกืคืจ ืฉืชืืืจ ืฆืจืื ืืืืืช ืืกืคืจ ื ืคืจื โ ืืกืคืจ ืืืขืืื ืืืื (ืืืฉ, ืื SIM ืืฉื ื ืฉืื ืืฉืืืืฉ). ืื ืื ืืืื, ืืื ืื ืืื ืืืื. โ ืื ืื ืืืืืืกืืค ืืจืฉืื ืืขืกืงืื โ ืืฉ ืกืืืื ืชืืืืจืื ืืืกืืื ืื ืืฉืชืืฉืื ืืืกืคืจ ืืืฉื.
- ืขืืืช: ื ืืกืืื ืืื ื ืฉื 3 ืืืื, ืืืจื ืื $6 ืืืืืฉ ืืืกืคืจ ืืื.
ืืืื ืืืชืืื?
Wait for confirmation.
Step 1 โ Sign up at Wasender
Tell the user:
- ืคืชื ืืช ืืืคืืคื ืืืฉ ื: https://wasenderapi.com
- ืืืฅ ืขื Sign Up ืืืฉืื ืืจืฉืื (ืืืืืื + ืกืืกืื).
- ืืืช ืืช ืืืืืืื.
- ืืืจื ืฉื ืื ืกืช โ ืชืืื ืื "ืืืืืจ" ืื ืืฉืื.
Wait until the user confirms.
Step 2 โ Get the Personal Access Token (PAT)
Tell the user:
ืืฆืืื. ืขืืฉืื ื ืืฆืืจ Personal Access Token โ ืืคืชื ืฉืืืคืฉืจ ืื ืื ืื ืืฉืื ืืช ืืืืืืจืื ืืืืืืกืืค.
- ืืฉ ื: https://wasenderapi.com/settings/tokens
- ืืืฅ Create New Token, ืชื ืื ืฉื (ืืืฉื "claude-code-builder").
- ืืขืชืง ืืช ืืืืจืืืช ืฉืชืืคืืข โ ืื ืืืืืื ืืช ืืืืืื ืฉืื ืืจืืืช ืืืชื.
- ืืืืง ืืช ืืืืจืืืช ืืื ืืฆ'ืื.
When the user pastes the token:
- Do not echo it back.
- Read the existing
.env file at the project root if it exists. If not, create it.
- Add or update the line
WASENDER_PAT=<the token>.
- Make sure
.env is in .gitignore. If not, add it.
- Confirm to the user:
ืืขืืื. ืฉืืจืชื ืืช ื-PAT ื-.env ืืงืืืืช (ืื ืืืขืื ื-Git, ืื ืืืื). ืขืืฉืื ื ืืฆืืจ ืืช ืืืืืืจ ืขืฆืื.
Step 3 โ Create a WhatsApp session via API
Ask the user for the phone number they'll connect:
ืืืื ืืกืคืจ ืืืคืื ืชืจืฆื ืืืืจ? (ืคืืจืื ืืื ืืืืื ืขื +, ืืืฉื +972501234567)
Validate format. Then ask:
ืืื ื ืงืจื ืืืืืืจ ืืื? (ืืืฉื "ืืกืืื ืฉื ืจืื ืช")
Then make the API call. Use Bash with curl. Pull the PAT from .env, never hardcode it in your prompt or output.
curl -sX POST "https://www.wasenderapi.com/api/whatsapp-sessions" \
-H "Authorization: Bearer $WASENDER_PAT" \
-H "Content-Type: application/json" \
-d "{
\"name\": \"$SESSION_NAME\",
\"phone_number\": \"$PHONE_NUMBER\",
\"account_protection\": true,
\"log_messages\": true,
\"webhook_enabled\": false
}"
(Webhook URL is registered later in wa-deploy once we have a public URL.)
The response shape:
{
"success": true,
"data": {
"id": 1,
"api_key": "75075a7bf6417bff59e76fb...",
"webhook_secret": "fb61be92ddb7935e0cedcec58e470f6c",
"status": "need_scan",
"phone_number": "+972501234567"
}
}
Parse the response. Save to .env:
WASENDER_SESSION_ID=<id>
WASENDER_API_KEY=<api_key>
WASENDER_WEBHOOK_SECRET=<webhook_secret>
WASENDER_PHONE=<phone_number>
Also update .wa-state.json:
{ "wasender_session_id": <id>, "wasender_phone": "<phone>" }
If the API returns success: false, surface the error message in Hebrew and stop. Common errors:
- 401: PAT is invalid โ ask the user to regenerate.
- 422: phone number format โ ask again with valid E.164.
- 402: plan limit reached โ tell the user to upgrade.
Step 4 โ Connect the session and fetch the QR
curl -sX POST "https://www.wasenderapi.com/api/whatsapp-sessions/$WASENDER_SESSION_ID/connect" \
-H "Authorization: Bearer $WASENDER_PAT"
Then poll for the QR:
curl -sX GET "https://www.wasenderapi.com/api/whatsapp-sessions/$WASENDER_SESSION_ID/qrcode" \
-H "Authorization: Bearer $WASENDER_PAT"
Response: {"success":true,"data":{"qrCode":"2@DfzdTHe..."}} โ the qrCode value is the raw WhatsApp QR string, not an image.
Render it as an image so the user can scan. Use Python:
python -c "
import qrcode, sys, os
qr_str = os.environ['QR_STR']
img = qrcode.make(qr_str)
img.save('wa-qr.png')
print('saved wa-qr.png')
"
If qrcode isn't installed, run pip install qrcode[pil] first. Save the image to the project root as wa-qr.png and tell the user:
ืืงืื ืืืื! ื ืฉืืจ ืืฆืื ืืื: wa-qr.png
ืขืืฉืื:
- ืคืชื ืืช ืืืืืืกืืค ืืืืคืื ืฉืืชื ืจืืฆื ืืืืจ.
- ืืืืจืืช โ ืืืฉืืจืื ืืงืืฉืจืื โ ืงืืฉืืจ ืืืฉืืจ.
- ืกืจืืง ืืช ืืงืืืฅ
wa-qr.png.
โฑ๏ธ ืืงืื ืชืงืฃ ื-45 ืฉื ืืืช. ืื ืคื ืชืืงืฃ, ืืืื ืื ืื ืืืฆืจ ืืืฉ.
Step 5 โ Wait for connection
Poll status every 3 seconds for up to 90 seconds:
curl -sX GET "https://www.wasenderapi.com/api/status" \
-H "Authorization: Bearer $WASENDER_API_KEY"
Response: {"success":true,"data":{"status":"connected"|"connecting"|"need_scan"|"disconnected"}}
connected โ success, move to step 6.
need_scan after 45s โ QR expired. Re-fetch QR, regenerate wa-qr.png, ask user to scan again.
disconnected โ ask user if they want to retry from the start.
When connected, delete wa-qr.png (no need to leave it lying around) and tell the user:
๐ ืืืืจ! ืืืกืคืจ {phone} ืืืืืจ ืขืืฉืื ืืจื Wasender.
Step 6 โ End-to-end verification
Send a test message from the bot back to itself (or to a number the user provides) to confirm outbound works.
Ask:
ืจืืฆื ืืฉืืื ืืืืขืช ืืืืงื? ืื ื ืืฉืื "ืฉืืื ืืืืื ืฉืื ๐" ืืืกืคืจ ืฉืชืืืจ. ืฉืื ืื ืืช ืืืกืคืจ (ืคืืจืื +).
Then:
curl -sX POST "https://www.wasenderapi.com/api/send-message" \
-H "Authorization: Bearer $WASENDER_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"to\":\"$TEST_NUMBER\",\"text\":\"ืฉืืื ืืืืื ืฉืื ๐\"}"
Verify response has success: true and data.msgId. Ask the user:
ืงืืืืช ืืช ืืืืืขื?
If yes โ done. If no โ diagnose: check status endpoint, check rate limit headers, check sender format.
Step 7 โ Update state and hand back
Update .wa-state.json:
{
"current_stage": "characterize",
"completed_stages": ["setup"],
"last_updated": "<ISO 8601>"
}
Tell the user:
ื ืืืจ! ืืืืืืจ ืขืืื. ืืฉืื ืืื ืืื ืืขืฆื ืืช ืืืืฉืืืช ืฉื ืืืื โ ืื ืืฉื ืฉืื, ืื ืืื ืืฉืจืช, ืืื ืืื ืืืืจ, ืื ืืืชืจ ืืื ืืกืืจ.
ืืืื ืืืืฉืื ืืฉืื ืืืืจืช ืืืคื ืืืื (/wa ืืฉืืืฃ ืืืชื ืืฉื)?
Hand back to /wa orchestrator.
Common pitfalls and how to handle
- PAT pasted with spaces or quotes. Strip whitespace and surrounding quotes before saving.
- User on free tier hits "1 request per minute" limit. When polling status, respect 3-second intervals โ don't burst. If 429 returned, wait longer.
- User has a previously deleted session with the same phone. The create call may return an error about duplicate phone. Tell the user we'll re-use the existing session โ call
GET /api/whatsapp-sessions (with PAT) to list, find the matching one, and adopt its id/api_key/webhook_secret.
qrcode Python lib not installed. Install via pip silently first; only mention it to the user if install fails.
- Webhook secret missing from response. This shouldn't happen on a fresh session, but if it does, regenerate via
PUT /api/whatsapp-sessions/{id} with regenerate_webhook_secret: true (verify against current docs if needed).