When developing applications that use A1Base webhooks, you’ll need a way to receive webhook events on your local development machine. This guide explains how to use Ngrok to create a secure tunnel to your local server.
Ngrok is a tool that creates secure tunnels from public URLs to your local machine, allowing external services like A1Base to send webhooks to your local development environment.
First, make sure your local webhook server is running. For A1Framework or NextJS you’ll run “npm run dev”. When you do this you’ll find out what port
your app is running on (e.g. localhost:3000).
Once your local server is running, use Ngrok to create a tunnel to your local port:
ngrok http 3000
This will start Ngrok and display output similar to:
Session Status onlineAccount Your Name (Plan: Free)Version 3.3.1Region United States (us)Latency 24msWeb Interface http://127.0.0.1:4040Forwarding https://a1b2-203-0-113-42.ngrok-free.app -> http://localhost:3000
The https://a1b2-203-0-113-42.ngrok-free.app URL is your public webhook URL that you’ll configure in the A1Base dashboard.
Ngrok free tier URLs change every time you restart Ngrok. You get one free consistent URL with Ngrok. For consistent URLs, consider upgrading to a paid plan.
Purchase Two Phone Numbers: In your A1Base dashboard, purchase two separate phone numbers
Label Your Numbers: Clearly label one as “Development” and one as “Production”
Configure Different Webhooks:
Development number: Point to your Ngrok URL
Production number: Point to your production server URL
Use Environment Variables: In your code, use environment variables to determine which phone number to use:
// Example of using different phone numbers based on environmentconst phoneNumber = process.env.NODE_ENV === 'production' ? process.env.A1BASE_PRODUCTION_PHONE : process.env.A1BASE_DEVELOPMENT_PHONE;// Use the appropriate phone number for outgoing messagesa1base.sendMessage({ to: recipientNumber, from: phoneNumber, message: "Hello from A1Base!"});
Free Tier Restrictions: Ngrok’s free tier has limitations on connections and features
URL Changes: Free Ngrok URLs change each time you restart Ngrok
Latency: There may be slight additional latency when using Ngrok
Security: Be cautious about sensitive data passing through your development environment
By following this guide, you can effectively test A1Base webhooks in your local development environment using Ngrok, ensuring a smooth transition to production.
{"docsConfig":{"$schema":"https://mintlify.com/docs.json","theme":"mint","name":"A1 Base","colors":{"primary":"#FC9E40","light":"#fdb968","dark":"#e88520"},"favicon":"/a1base-favicon.png","logo":{"light":"https://mintcdn.com/a1base/xTxzAsXkiIECWmJ2/logo/black-brandmark-300px.png?fit=max\u0026auto=format\u0026n=xTxzAsXkiIECWmJ2\u0026q=85\u0026s=1b24b806316d22f2f89976bd7c383f5e","dark":"https://mintcdn.com/a1base/xTxzAsXkiIECWmJ2/logo/white-brandmark-300px.png?fit=max\u0026auto=format\u0026n=xTxzAsXkiIECWmJ2\u0026q=85\u0026s=3d119acb4126641ab79802db42761f83"},"navbar":{"links":[{"label":"Support","href":"mailto:[email protected]"}],"primary":{"type":"button","label":"Dashboard","href":"https://a1base.com"}},"footer":{"socials":{"x":"https://x.com/a1baseapi","github":"https://github.com/a1baseai","linkedin":"https://www.linkedin.com/company/a1base/"}},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"a1base","hasAudioNarration":false,"actualSubdomain":"a1base","customDomains":["docs.a1base.com"],"gitSource":{"type":"github","owner":"pasharayan","repo":"docs","deployBranch":"main","contentDirectory":"","isPrivate":false,"mountPath":"","label":""},"chroma":{"liveDeploymentHistoryId":"6a21e668572b750f6b6fa112","collectionId":"a898072e-031c-4f34-9ed8-32e5becc83f6","schemaVersion":"v2"},"entitlements":{"AI_CHAT":{"status":"DISABLED"}},"buildId":"6a21e668572b750f6b6fa112:success","clientVersion":"0.0.4045","searchFilterCounts":[{"language":"default","tag":"Documentation","count":49},{"language":"default","tag":"A1Cron","count":14},{"language":"default","tag":"API Reference","count":11},{"language":"default","tag":"A1Mail","count":8},{"language":"default","tag":"Cron Job Management","count":6},{"language":"default","tag":"Getting Started with A1Cron","count":4},{"language":"default","tag":"Email API","count":4},{"language":"default","tag":"Thread Endpoints","count":4},{"language":"default","tag":"A1Zap","count":3},{"language":"default","tag":"🚀 Get Started","count":3}]},"assistantConfig":{},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"byok-sep-25","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"vite-origin","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-updated-9-15","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[],"page":{"pagePath":"troubleshooting/local-testing-with-ngrok","slug":"/troubleshooting/local-testing-with-ngrok","pageMetadata":{"title":"Local Testing with Ngrok","description":"How to use Ngrok to test A1Base webhooks in your local development environment","href":"/troubleshooting/local-testing-with-ngrok"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"How to use Ngrok to test A1Base webhooks in your local development environment\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,li:`li`,ol:`ol`,p:`p`,pre:`pre`,span:`span`,strong:`strong`,ul:`ul`,..._provideComponents(),...props.components},{CodeBlock,Heading,Note,Tip,Warning}=_components;if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Note)_missingMdxReference(`Note`,true);if(!Tip)_missingMdxReference(`Tip`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsx(Heading,{level:`1`,id:`testing-webhooks-locally-with-ngrok`,children:`Testing Webhooks Locally with Ngrok`}),`\n`,_jsx(_components.p,{children:`When developing applications that use A1Base webhooks, you’ll need a way to receive webhook events on your local development machine. This guide explains how to use Ngrok to create a secure tunnel to your local server.`}),`\n`,_jsx(Heading,{level:`2`,id:`what-is-ngrok`,children:`What is Ngrok?`}),`\n`,_jsx(_components.p,{children:`Ngrok is a tool that creates secure tunnels from public URLs to your local machine, allowing external services like A1Base to send webhooks to your local development environment.`}),`\n`,_jsx(Heading,{level:`2`,id:`setting-up-ngrok`,children:`Setting Up Ngrok`}),`\n`,_jsx(Heading,{level:`3`,id:`step-1-install-ngrok`,children:`Step 1: Install Ngrok`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Visit `,_jsx(_components.a,{href:`https://ngrok.com/`,children:`ngrok.com`}),` and sign up for a free account`]}),`\n`,_jsx(_components.li,{children:`Download and install Ngrok for your operating system`}),`\n`,_jsx(_components.li,{children:`Authenticate your Ngrok installation with your auth token:`}),`\n`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`ngrok`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` config`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` add-authtoken`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` YOUR_AUTH_TOKEN`})]}),`\n`]})})}),`\n`,_jsx(Heading,{level:`3`,id:`step-2-start-your-local-server`,children:`Step 2: Start Your Local Server`}),`\n`,_jsx(_components.p,{children:`First, make sure your local webhook server is running. For A1Framework or NextJS you’ll run “npm run dev”. When you do this you’ll find out what port\nyour app is running on (e.g. localhost:3000).`}),`\n`,_jsx(Heading,{level:`3`,id:`step-3-connect-ngrok-to-your-local-port`,children:`Step 3: Connect Ngrok to Your Local Port`}),`\n`,_jsx(_components.p,{children:`Once your local server is running, use Ngrok to create a tunnel to your local port:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`ngrok`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` http`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 3000`})]}),`\n`]})})}),`\n`,_jsx(_components.p,{children:`This will start Ngrok and display output similar to:`}),`\n`,_jsx(CodeBlock,{numberOfLines:`8`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`8`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Session Status online`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Account Your Name (Plan: Free)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Version 3.3.1`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Region United States (us)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Latency 24ms`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Web Interface http://127.0.0.1:4040`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Forwarding https://a1b2-203-0-113-42.ngrok-free.app -> http://localhost:3000`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),`\n`,_jsxs(_components.p,{children:[`The `,_jsx(_components.code,{children:`https://a1b2-203-0-113-42.ngrok-free.app`}),` URL is your public webhook URL that you’ll configure in the A1Base dashboard.`]}),`\n`,_jsx(Warning,{children:_jsx(_components.p,{children:`Ngrok free tier URLs change every time you restart Ngrok. You get one free consistent URL with Ngrok. For consistent URLs, consider upgrading to a paid plan.`})}),`\n`,_jsx(Heading,{level:`2`,id:`configuring-a1base-with-your-ngrok-url`,children:`Configuring A1Base with Your Ngrok URL`}),`\n`,_jsx(_components.p,{children:`To configure your Ngrok URL in the A1Base dashboard, follow these steps:`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Log in to the A1Base dashboard at `,_jsx(_components.a,{href:`https://www.a1base.com/dashboard/phone-numbers`,children:`https://www.a1base.com/dashboard/phone-numbers`}),`.`]}),`\n`,_jsx(_components.li,{children:`Navigate to the “Phone Numbers” section and locate the phone number you wish to configure (e.g., 14155356190).`}),`\n`,_jsxs(_components.li,{children:[`In the “Webhook URL” column for that phone number, enter your Ngrok HTTPS URL combined with your endpoint path (e.g., `,_jsx(_components.a,{href:`https://a1b2-203-0-113-42.ngrok-free.app/whatsapp/incoming`,children:`https://a1b2-203-0-113-42.ngrok-free.app/whatsapp/incoming`}),`).`]}),`\n`,_jsxs(_components.li,{children:[`Click the “Save” button next to the webhook URL field to apply the changes.\n`,_jsxs(Note,{children:[` Refer to the A1Base dashboard screenshot for a visual guide on configuring webhook URLs: `,_jsx(_components.a,{href:`link-to-screenshot`,children:`Phone Numbers Dashboard`}),`. `]})]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`development-vs-production-phone-numbers`,children:`Development vs. Production Phone Numbers`}),`\n`,_jsx(Tip,{children:_jsx(_components.p,{children:`For a smooth development workflow, we recommend purchasing two separate phone numbers on A1Base: one for development and one for production.`})}),`\n`,_jsx(Heading,{level:`3`,id:`why-use-separate-phone-numbers`,children:`Why Use Separate Phone Numbers?`}),`\n`,_jsx(_components.p,{children:`Using separate phone numbers for development and production environments offers several advantages:`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Isolated Testing`}),`: Test new features without affecting your production users`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Prevent Webhook Conflicts`}),`: Avoid routing production messages to your development environment`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Easier Debugging`}),`: Clearly distinguish between development and production traffic`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Safer Experimentation`}),`: Experiment with new features risk-free`]}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`setting-up-development-and-production-numbers`,children:`Setting Up Development and Production Numbers`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Purchase Two Phone Numbers`}),`: In your A1Base dashboard, purchase two separate phone numbers`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Label Your Numbers`}),`: Clearly label one as “Development” and one as “Production”`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Configure Different Webhooks`}),`:`,`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Development number: Point to your Ngrok URL`}),`\n`,_jsx(_components.li,{children:`Production number: Point to your production server URL`}),`\n`]}),`\n`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Use Environment Variables`}),`: In your code, use environment variables to determine which phone number to use:`]}),`\n`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`11`,language:`javascript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`javascript`,children:_jsxs(_components.code,{language:`javascript`,numberOfLines:`11`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// Example of using different phone numbers based on environment`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`const`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` phoneNumber`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` process`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`env`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:`NODE_ENV`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` ===`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 'production'`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` ?`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` process`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`env`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:`A1BASE_PRODUCTION_PHONE`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` :`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` process`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`env`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:`A1BASE_DEVELOPMENT_PHONE`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`;`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// Use the appropriate phone number for outgoing messages`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`a1base`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`sendMessage`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`({`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` to:`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` recipientNumber`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` from:`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` phoneNumber`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` message:`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"Hello from A1Base!\"`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`});`})}),`\n`]})})}),`\n`,_jsx(Heading,{level:`2`,id:`monitoring-webhook-traffic`,children:`Monitoring Webhook Traffic`}),`\n`,_jsxs(_components.p,{children:[`Ngrok provides a web interface at `,_jsx(_components.code,{children:`http://127.0.0.1:4040`}),` where you can inspect:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`All incoming webhook requests`}),`\n`,_jsx(_components.li,{children:`Request and response headers`}),`\n`,_jsx(_components.li,{children:`Request and response bodies`}),`\n`,_jsx(_components.li,{children:`Timing information`}),`\n`]}),`\n`,_jsx(_components.p,{children:`This interface is invaluable for debugging webhook issues during development.`}),`\n`,_jsx(Heading,{level:`2`,id:`best-practices-for-local-testing`,children:`Best Practices for Local Testing`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Keep Ngrok Running`}),`: Maintain your Ngrok session while testing to avoid URL changes`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Log All Webhook Data`}),`: Implement comprehensive logging in your development environment`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Simulate Different Scenarios`}),`: Test various message types and edge cases`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Verify Webhook Signatures`}),`: Even in development, validate webhook signatures if available`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Test Error Handling`}),`: Ensure your application handles webhook failures gracefully`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`limitations-and-considerations`,children:`Limitations and Considerations`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Free Tier Restrictions`}),`: Ngrok’s free tier has limitations on connections and features`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`URL Changes`}),`: Free Ngrok URLs change each time you restart Ngrok`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Latency`}),`: There may be slight additional latency when using Ngrok`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Security`}),`: Be cautious about sensitive data passing through your development environment`]}),`\n`]}),`\n`,_jsx(_components.p,{children:`By following this guide, you can effectively test A1Base webhooks in your local development environment using Ngrok, ensuring a smooth transition to production.`})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Local Testing with Ngrok","description":"How to use Ngrok to test A1Base webhooks in your local development environment","href":"/troubleshooting/local-testing-with-ngrok"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"Testing Webhooks Locally with Ngrok","slug":"testing-webhooks-locally-with-ngrok","depth":1,"children":[]},{"title":"What is Ngrok?","slug":"what-is-ngrok","depth":2,"children":[]},{"title":"Setting Up Ngrok","slug":"setting-up-ngrok","depth":2,"children":[{"title":"Step 1: Install Ngrok","slug":"step-1-install-ngrok","depth":3,"children":[]},{"title":"Step 2: Start Your Local Server","slug":"step-2-start-your-local-server","depth":3,"children":[]},{"title":"Step 3: Connect Ngrok to Your Local Port","slug":"step-3-connect-ngrok-to-your-local-port","depth":3,"children":[]}]},{"title":"Configuring A1Base with Your Ngrok URL","slug":"configuring-a1base-with-your-ngrok-url","depth":2,"children":[]},{"title":"Development vs. Production Phone Numbers","slug":"development-vs-production-phone-numbers","depth":2,"children":[{"title":"Why Use Separate Phone Numbers?","slug":"why-use-separate-phone-numbers","depth":3,"children":[]},{"title":"Setting Up Development and Production Numbers","slug":"setting-up-development-and-production-numbers","depth":3,"children":[]}]},{"title":"Monitoring Webhook Traffic","slug":"monitoring-webhook-traffic","depth":2,"children":[]},{"title":"Best Practices for Local Testing","slug":"best-practices-for-local-testing","depth":2,"children":[]},{"title":"Limitations and Considerations","slug":"limitations-and-considerations","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":[],"subdomain":"a1base","siteName":"A1 Base","title":"Local Testing with Ngrok - A1 Base","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-01-07T04:48:13.160Z","originalFileLocation":"troubleshooting/local-testing-with-ngrok.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"How to use Ngrok to test A1Base webhooks in your local development environment\">\u003cmeta data-mint-head name=\"application-name\" content=\"A1 Base\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/a1base/xU09ej1j_CDmQY5d/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/a1base/xU09ej1j_CDmQY5d/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/a1base/xU09ej1j_CDmQY5d/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/a1base/xU09ej1j_CDmQY5d/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/a1base/xU09ej1j_CDmQY5d/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/a1base/xU09ej1j_CDmQY5d/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/a1base/xU09ej1j_CDmQY5d/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/a1base/xU09ej1j_CDmQY5d/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/a1base/xU09ej1j_CDmQY5d/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Local Testing with Ngrok - A1 Base\">\u003cmeta data-mint-head property=\"og:description\" content=\"How to use Ngrok to test A1Base webhooks in your local development environment\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"A1 Base\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.a1base.com/troubleshooting/local-testing-with-ngrok\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://a1base.mintlify.app/_mintlify/api/og/v2?division=Troubleshooting\u0026amp;title=Local+Testing+with+Ngrok\u0026amp;description=How+to+use+Ngrok+to+test+A1Base+webhooks+in+your+local+development+environment\u0026amp;theme=e761769d2690409d71d34748\u0026amp;signature=e4c2c0ea75d3b55b6171d69b45535090d852811461eb95e6df4bbba478564c8e\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Local Testing with Ngrok - A1 Base\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"How to use Ngrok to test A1Base webhooks in your local development environment\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://a1base.mintlify.app/_mintlify/api/og/v2?division=Troubleshooting\u0026amp;title=Local+Testing+with+Ngrok\u0026amp;description=How+to+use+Ngrok+to+test+A1Base+webhooks+in+your+local+development+environment\u0026amp;theme=e761769d2690409d71d34748\u0026amp;signature=e4c2c0ea75d3b55b6171d69b45535090d852811461eb95e6df4bbba478564c8e\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/a1base/xU09ej1j_CDmQY5d/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"A1 Base\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#FC9E40\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.a1base.com/troubleshooting/local-testing-with-ngrok\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/troubleshooting/local-testing-with-ngrok.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.a1base.com/#organization\",\"name\":\"A1 Base\",\"url\":\"https://docs.a1base.com\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/a1base/xTxzAsXkiIECWmJ2/logo/black-brandmark-300px.png?fit=max\u0026auto=format\u0026n=xTxzAsXkiIECWmJ2\u0026q=85\u0026s=1b24b806316d22f2f89976bd7c383f5e\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.a1base.com#website\",\"name\":\"A1 Base\",\"url\":\"https://docs.a1base.com\",\"publisher\":{\"@id\":\"https://docs.a1base.com/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.a1base.com/troubleshooting/local-testing-with-ngrok#webpage\",\"url\":\"https://docs.a1base.com/troubleshooting/local-testing-with-ngrok\",\"name\":\"Local Testing with Ngrok\",\"description\":\"How to use Ngrok to test A1Base webhooks in your local development environment\",\"dateModified\":\"2026-01-07T04:48:13.160Z\",\"isPartOf\":{\"@id\":\"https://docs.a1base.com#website\"},\"breadcrumb\":{\"@id\":\"https://docs.a1base.com/troubleshooting/local-testing-with-ngrok#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.a1base.com/troubleshooting/local-testing-with-ngrok#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Troubleshooting\",\"item\":\"https://docs.a1base.com/troubleshooting/webhook-issues\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Local Testing with Ngrok\",\"item\":\"https://docs.a1base.com/troubleshooting/local-testing-with-ngrok\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://docs.a1base.com/troubleshooting/local-testing-with-ngrok#article\",\"headline\":\"Local Testing with Ngrok\",\"name\":\"Local Testing with Ngrok\",\"description\":\"How to use Ngrok to test A1Base webhooks in your local development environment\",\"url\":\"https://docs.a1base.com/troubleshooting/local-testing-with-ngrok\",\"mainEntityOfPage\":{\"@id\":\"https://docs.a1base.com/troubleshooting/local-testing-with-ngrok#webpage\"},\"dateModified\":\"2026-01-07T04:48:13.160Z\",\"publisher\":{\"@id\":\"https://docs.a1base.com/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.a1base.com#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"A1 Base\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"A1 Base","nav":{"global":null,"anchors":[{"anchor":"Documentation","icon":"book-open","tabs":[{"tab":"Documentation","groups":[{"group":"🚀 Get Started","pages":[{"title":"Overview","href":"/introduction"},{"title":"Quickstart","href":"/quickstart"},{"title":"Spam \u0026 Quality Checks","href":"/spam-and-quality-checks"}]},{"group":"Features","pages":[{"title":"Cron Jobs","href":"/cron-jobs"},{"title":"Troubleshooting","href":"/troubleshooting"}]},{"group":"Troubleshooting","pages":[{"title":"Webhook Issues","description":"Troubleshooting common webhook problems and how to resolve them","href":"/troubleshooting/webhook-issues"},{"title":"Local Testing with Ngrok","href":"/troubleshooting/local-testing-with-ngrok"}]},{"group":"NodeJS","pages":[{"title":"Introduction","description":"Using the A1Base API to send, receive, and manage messages","href":"/node-js/introduction"}]}]},{"tab":"API Reference","pages":[{"title":"API Reference","href":"/api-reference/introduction"}]},{"tab":"A1Mail","pages":[{"title":"A1Mail","href":"/a1mail"}]},{"tab":"A1Cron","pages":[{"title":"A1Cron","href":"/a1cron"}]},{"tab":"A1Zap","pages":[{"title":"A1Zap","href":"/a1zap"}]}]},{"anchor":"Support","href":"mailto:[email protected]","icon":"envelope"}]},"basePath":"","title":"Local Testing with Ngrok - A1 Base","buildId":"dpl_36EDyZCDfRuoUD9af5CH4M1bqY2h","deploymentId":"dpl_36EDyZCDfRuoUD9af5CH4M1bqY2h","dynamics":[],"chunks":[]}