Why use a sandbox
Connecting your own WhatsApp number or Instagram account goes through Meta, which takes real setup: a verified business, a phone number, and app permissions. The sandbox skips all of that, so you can:- Try HookMyApp end to end before committing your own number or account.
- Build and test your webhook handler on your own laptop.
- Develop safely, without touching your real account or messaging real customers.
How it works
You pin a session to your own phone so the sandbox knows the messages are yours:- You receive only the messages your pinned phone sends to the test account.
- You can reply only to your pinned phone.
Limitations
The sandbox is for testing, not for real traffic:- You can only message your own pinned phone. You cannot message other people; the sandbox rejects any other recipient.
- Sessions expire after 24 hours of inactivity. Start a session again to get fresh credentials.
- When you are ready for real customers, connect your own WhatsApp number or Instagram account instead.
Start a session
sandbox start prints an 8-char bind code and a QR. WhatsApp that code to the sandbox number from the phone you want to bind. That inbound message is what pins the session to your phone (it proves you control the number). Open the QR’s wa.me link on the same phone to auto-fill.
For Instagram, run hookmyapp sandbox start instagram. The CLI prints an ig.me deep link to the sandbox Instagram account. DM the account to pin your session. When you have more than one session, select the Instagram one by handle with --username <@handle> on sandbox env, sandbox send, sandbox logs, and sandbox webhook.
Pull env values
Write the sandbox env values to a.env file your server can load.
VERIFY_TOKEN: the HMAC secret your server uses to verifyX-HookMyApp-Signature-256on incoming webhooks.PORT: where your local server listens. Defaults to3000.WHATSAPP_API_URL: the sandbox proxy URL your app POSTs messages to.WHATSAPP_ACCESS_TOKEN: the session activation code, used as the Bearer token.WHATSAPP_PHONE_NUMBER_ID: the ID of the test number.
VERIFY_TOKEN: same HMAC secret role as above.PORT: where your local server listens. Defaults to3000.INSTAGRAM_API_URL: the sandbox proxy URL your app POSTs messages to.INSTAGRAM_ACCESS_TOKEN: the session activation code, used as the Bearer token.INSTAGRAM_ACCOUNT_ID: the ID of the test Instagram account.
Sandbox keys differ from a real channel. A real connected Instagram channel (
hookmyapp channels env <channel>) emits INSTAGRAM_GRAPH_API_URL and INSTAGRAM_USER_ID instead of the sandbox INSTAGRAM_API_URL and INSTAGRAM_ACCOUNT_ID. The request shape is identical; only these key names change.Session lifecycle
- Activate:
hookmyapp sandbox startissues a bind code; WhatsApp it from the phone you want to bind to pin a session. - Expiry: sessions expire after 24 hours idle.
- Reactivate: run
hookmyapp sandbox startagain and WhatsApp the new code from the same phone. You get a fresh activation code and new env values. - Stop early:
hookmyapp sandbox stoptears down the session immediately.
Inspect and configure
hookmyapp sandbox logsstreams the session’s delivery log. Add--followto tail it live and--verbosefor full bodies.hookmyapp sandbox webhook showprints the current sandbox tunnel destination.hookmyapp sandbox webhook setoverrides it andhookmyapp sandbox webhook clearreverts to the CLI-managed default.
Local tunneling
To stream inbound webhooks to localhost, open a secure tunnel withhookmyapp sandbox listen. The tunnel connects a HookMyApp-managed public hostname (sandbox.hookmyapp.com) to http://localhost:3000/webhook by default, and lives as long as the CLI process runs. The CLI picks the hostname automatically; you don’t configure it.
Send a test message
The sandbox only sends to your pinned phone. There is no--to flag on sandbox send; the sandbox proxy rejects other recipients.
Next steps
- WhatsApp quickstart: Pair the sandbox with the reference receiver in two minutes.
- Instagram quickstart: The same loop for Instagram DMs.
- Webhook routing: See how the sandbox and your own channel’s URLs differ.