You run Routr and a NATS server with Docker Compose, turn on EdgePort’s NATS publisher, and subscribe to the events with the nats CLI. When you register two softphones and call between them, you see routr.endpoint.registered, routr.call.started, and routr.call.ended messages arrive.Call events come from EdgePort, so you can feed them to billing, dashboards, or any service that speaks NATS without touching the SIP path.
Create a folder for the tutorial and a compose.yaml file inside it. It runs a NATS server and routr-one with the NATS publisher turned on.Filename: compose.yaml
The --insecure flag is required because this setup doesn’t use TLS on the API.
5
Register the softphones
Configure each softphone with one Agent: its username and password, sip.local as the domain, and your machine’s IP (for example, 192.168.1.3:5060) as the outbound proxy over UDP.Each successful registration publishes an event.
[#1] Received on "routr.endpoint.registered"{"aor":"sip:1001@sip.local","registeredAt":"2026-10-21T15:02:11.482Z","expires":600,"extraHeaders":{}}
You see one routr.endpoint.registered message per softphone. Softphones re-register periodically, so more arrive over time.
6
Make a call
From 1001, call 1002. When Routr forwards the INVITE, EdgePort publishes routr.call.started.
[#3] Received on "routr.call.started"{"callId":"_Ax7XxHju-o7fbemWxxLww..","from":"sip:1001@sip.local","to":"sip:1002@sip.local","startTime":"2026-10-21T15:03:10.111Z","extraHeaders":{}}
Hang up. EdgePort publishes routr.call.ended with the same callId.
[#4] Received on "routr.call.ended"{"callId":"_Ax7XxHju-o7fbemWxxLww..","endTime":"2026-10-21T15:03:55.760Z","hangupCause":"NORMAL_CLEARING","extraHeaders":{}}
routr.call.started as shown by nats sub (captured on an earlier release, so the fields differ slightly)
routr.call.ended as shown by nats sub (captured on an earlier release)
For one call you see one routr.call.started and one routr.call.ended, and both carry the same callId.
callId, from, to, startTime, extraHeaders, plus any metadata the processor attached to the route
routr.call.ended
A BYE or CANCEL completes, an INVITE fails with a status above 300, or a transport error drops the transaction
callId, endTime, hangupCause, extraHeaders
extraHeaders holds every header in the message whose name starts with X-. For a list of hangup causes, see HangupCauses.java.To change the prefix, set NATS_PUBLISHER_SUBJECT. For example, NATS_PUBLISHER_SUBJECT=myserver publishes myserver.call.started, myserver.call.ended, and myserver.endpoint.registered.
To print events to EdgePort’s log instead of NATS while you debug, set CONSOLE_PUBLISHER_ENABLED=true.
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Routr","description":"Routr is a programmable SIP proxy, registrar and location server built as a set of cloud-native gRPC services.","colors":{"primary":"#1F8F8E","light":"#5FCFCE","dark":"#1F8F8E"},"logo":{"light":"https://mintcdn.com/routr-docs/iaqIipuuzAjyl_cH/logo/light.svg?fit=max\u0026auto=format\u0026n=iaqIipuuzAjyl_cH\u0026q=85\u0026s=46cd1037119709d8341f90de12fdd541","dark":"https://mintcdn.com/routr-docs/iaqIipuuzAjyl_cH/logo/dark.svg?fit=max\u0026auto=format\u0026n=iaqIipuuzAjyl_cH\u0026q=85\u0026s=b340179f328e1846b168b53e0cf261dd","href":"https://routr.io"},"favicon":"https://mintcdn.com/routr-docs/iaqIipuuzAjyl_cH/favicon.svg?fit=max\u0026auto=format\u0026n=iaqIipuuzAjyl_cH\u0026q=85\u0026s=d0eb6868d8786cdfaab5b72affaa3d20","appearance":{"default":"dark"},"background":{"color":{"light":"#FFFFFF","dark":"#181818"}},"navbar":{"links":[{"href":"https://routr.io","label":"Website"},{"href":"https://github.com/fonoster/routr/discussions","label":"Discussions"}],"primary":{"type":"github","href":"https://github.com/fonoster/routr"}},"footer":{"socials":{"x":"https://x.com/fonoster","github":"https://github.com/fonoster/routr","linkedin":"https://linkedin.com/company/fonoster"}},"fonts":{"heading":{"family":"Poppins","weight":600},"body":{"family":"Poppins"}},"styling":{"codeblocks":"system","latex":false},"contextual":{"options":["copy","view","chatgpt","claude","perplexity","cursor","vscode"],"display":"header"},"navigation":{"global":{"anchors":[{"anchor":"GitHub","icon":"github","href":"https://github.com/fonoster/routr"},{"anchor":"Community","icon":"discord","href":"https://discord.gg/4QWgSz4hTC"},{"anchor":"Previous versions","icon":"clock-rotate-left","href":"/previous-versions"}]},"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"routr-docs","hasAudioNarration":false,"actualSubdomain":"routr-docs","customDomains":["docs.routr.io"],"gitSource":{"type":"github","owner":"fonoster","repo":"routr","deployBranch":"main","contentDirectory":"docs-site","isPrivate":true,"mountPath":"","label":"","_id":"6ad98ce6a48533467ae0274a"},"chroma":{"latestBuiltDeploymentHistoryId":"6ad98ce9a48533467ae02757","collectionId":"7e3efbde-ef83-4bd9-a2d7-8a87b4140fb6","liveDeploymentHistoryId":"6ad98ce9a48533467ae02757","schemaVersion":"v3"},"entitlements":{},"buildId":"6ad98f3ba48533467ae03dcc","clientVersion":"0.0.3926","searchFilterCounts":[{"language":"default","tag":"Docs","count":33},{"language":"default","tag":"Reference","count":23},{"language":"default","tag":"How-to guides","count":15},{"language":"default","tag":"Components","count":9},{"language":"default","tag":"Connect resources","count":8},{"language":"default","tag":"Concepts","count":7},{"language":"default","tag":"Tutorials","count":5},{"language":"default","tag":"Extend Routr","count":4},{"language":"default","tag":"Deploy and operate","count":4},{"language":"default","tag":"Community","count":3}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableContextualStarterQuestions":false,"enableAskAiSearchBar":true},"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":"editor-v7-file-tree","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":"pause-universal-search-reconcile","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":"per-site-search-delta","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":"editor-private-page-search","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":"editor-nav-generations","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":"vite-origin","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":"editor-agent-model-picker","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}],"isAtlas":false,"googleFontsInlined":true},"customCss":[{"filePath":"style.css","content":"/* cyrillic-ext */\n@font-face {\n font-family: 'Roboto Mono';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/robotomono/v31/L0x5DF4xlVMF-BfR8bXMIjhGq3-OXg.woff2) format('woff2');\n unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;\n}\n/* cyrillic */\n@font-face {\n font-family: 'Roboto Mono';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/robotomono/v31/L0x5DF4xlVMF-BfR8bXMIjhPq3-OXg.woff2) format('woff2');\n unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;\n}\n/* greek */\n@font-face {\n font-family: 'Roboto Mono';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/robotomono/v31/L0x5DF4xlVMF-BfR8bXMIjhIq3-OXg.woff2) format('woff2');\n unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;\n}\n/* vietnamese */\n@font-face {\n font-family: 'Roboto Mono';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/robotomono/v31/L0x5DF4xlVMF-BfR8bXMIjhEq3-OXg.woff2) format('woff2');\n unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;\n}\n/* latin-ext */\n@font-face {\n font-family: 'Roboto Mono';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/robotomono/v31/L0x5DF4xlVMF-BfR8bXMIjhFq3-OXg.woff2) format('woff2');\n unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n font-family: 'Roboto Mono';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/robotomono/v31/L0x5DF4xlVMF-BfR8bXMIjhLq38.woff2) format('woff2');\n unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n}\n/* cyrillic-ext */\n@font-face {\n font-family: 'Roboto Mono';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/robotomono/v31/L0x5DF4xlVMF-BfR8bXMIjhGq3-OXg.woff2) format('woff2');\n unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;\n}\n/* cyrillic */\n@font-face {\n font-family: 'Roboto Mono';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/robotomono/v31/L0x5DF4xlVMF-BfR8bXMIjhPq3-OXg.woff2) format('woff2');\n unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;\n}\n/* greek */\n@font-face {\n font-family: 'Roboto Mono';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/robotomono/v31/L0x5DF4xlVMF-BfR8bXMIjhIq3-OXg.woff2) format('woff2');\n unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;\n}\n/* vietnamese */\n@font-face {\n font-family: 'Roboto Mono';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/robotomono/v31/L0x5DF4xlVMF-BfR8bXMIjhEq3-OXg.woff2) format('woff2');\n unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;\n}\n/* latin-ext */\n@font-face {\n font-family: 'Roboto Mono';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/robotomono/v31/L0x5DF4xlVMF-BfR8bXMIjhFq3-OXg.woff2) format('woff2');\n unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n font-family: 'Roboto Mono';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/robotomono/v31/L0x5DF4xlVMF-BfR8bXMIjhLq38.woff2) format('woff2');\n unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n}\n:root{--fn-accent:#5fcfce;--fn-on-accent:#001a1a;--fn-accent-text:#1f8f8e;--fn-border:#e8e8e8;--fn-hl-border:rgba(0, 0, 0, 0.22);--fn-surface:#f4f4f4;--fn-text-1:#252525;--fn-text-2:#555555;--fn-text-3:#6b6b6b;--fn-mono:\"Roboto Mono\", ui-monospace, monospace}:root.dark{--fn-accent-text:#5fcfce;--fn-border:#333333;--fn-hl-border:rgba(255, 255, 255, 0.32);--fn-surface:#202020;--fn-text-1:#ffffff;--fn-text-2:#e8e8e8;--fn-text-3:#c2c2c2}#content-area h1,#header h1{font-weight:600;letter-spacing:-.031em}#content-area h2{font-weight:600;letter-spacing:-.027em}#content-area h3{font-weight:600;letter-spacing:-.025em}#content-area li,#content-area p{color:var(--fn-text-2)}.eyebrow{font-family:var(--fn-mono);font-weight:500;font-size:12px;letter-spacing:.12em;text-transform:uppercase}code,kbd,pre{font-family:var(--fn-mono)!important}#content-area :not(pre)>code{border:1px solid var(--fn-border);border-radius:6px;padding:1px 6px}#content-area .card,#content-area .code-block,#content-area [class*=callout],#content-area pre,#topbar-cta-button a,#topbar-cta-button a>span{border-radius:10px}#content-area a.card:hover{border-color:var(--fn-hl-border)}#topbar-cta-button a>span:first-child{background:var(--fn-accent)!important}#topbar-cta-button a span,#topbar-cta-button a svg{color:var(--fn-on-accent)!important;font-weight:600}"}],"page":{"pagePath":"tutorials/call-events-with-nats","slug":"/tutorials/call-events-with-nats","pageMetadata":{"title":"Stream call events to NATS","sidebarTitle":"Call events with NATS","description":"Turn on EdgePort's NATS publisher, subscribe with the nats CLI, and see an event for every registration, call start, and call end.","href":"/tutorials/call-events-with-nats"},"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: \"Turn on EdgePort’s NATS publisher, subscribe with the nats CLI, and see an event for every registration, call start, and call end.\"\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`,p:`p`,pre:`pre`,span:`span`,tbody:`tbody`,td:`td`,th:`th`,thead:`thead`,tr:`tr`,ul:`ul`,..._provideComponents(),...props.components},{Card,CardGroup,Check,CodeBlock,Frame,Heading,OptimizedImage,Step,Steps,Table,Tip}=_components;if(!Card)_missingMdxReference(`Card`,true);if(!CardGroup)_missingMdxReference(`CardGroup`,true);if(!Check)_missingMdxReference(`Check`,true);if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Frame)_missingMdxReference(`Frame`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!OptimizedImage)_missingMdxReference(`OptimizedImage`,true);if(!Step)_missingMdxReference(`Step`,true);if(!Steps)_missingMdxReference(`Steps`,true);if(!Table)_missingMdxReference(`Table`,true);if(!Tip)_missingMdxReference(`Tip`,true);return _jsxs(_Fragment,{children:[_jsx(Heading,{level:`2`,id:`what-you’ll-build`,children:`What you’ll build`}),`\n`,_jsxs(_components.p,{children:[`You run Routr and a NATS server with Docker Compose, turn on EdgePort’s NATS publisher, and subscribe to the events with the `,_jsx(_components.code,{children:`nats`}),` CLI. When you register two softphones and call between them, you see `,_jsx(_components.code,{children:`routr.endpoint.registered`}),`, `,_jsx(_components.code,{children:`routr.call.started`}),`, and `,_jsx(_components.code,{children:`routr.call.ended`}),` messages arrive.`]}),`\n`,_jsx(_components.p,{children:`Call events come from EdgePort, so you can feed them to billing, dashboards, or any service that speaks NATS without touching the SIP path.`}),`\n`,_jsx(Heading,{level:`2`,id:`prerequisites`,children:`Prerequisites`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Docker with Docker Compose`}),`\n`,_jsxs(_components.li,{children:[`The `,_jsxs(_components.a,{href:`https://github.com/nats-io/natscli`,children:[_jsx(_components.code,{children:`nats`}),` CLI`]})]}),`\n`,_jsxs(_components.li,{children:[`Node.js and npm, to install `,_jsx(_components.code,{children:`rctl`})]}),`\n`,_jsx(_components.li,{children:`Two SIP softphones`}),`\n`,_jsxs(_components.li,{children:[`The IP address of your machine on your local network (for example, `,_jsx(_components.code,{children:`192.168.1.3`}),`)`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`steps`,children:`Steps`}),`\n`,_jsxs(Steps,{children:[_jsxs(Step,{title:`Define the services`,children:[_jsxs(_components.p,{children:[`Create a folder for the tutorial and a `,_jsx(_components.code,{children:`compose.yaml`}),` file inside it. It runs a NATS server and `,_jsx(_components.code,{children:`routr-one`}),` with the NATS publisher turned on.`]}),_jsxs(_components.p,{children:[`Filename: `,_jsx(_components.code,{children:`compose.yaml`})]}),_jsx(CodeBlock,{filename:``,numberOfLines:`18`,language:`yaml`,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:`yaml`,children:_jsxs(_components.code,{language:`yaml`,numberOfLines:`18`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`services`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` nats`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` image`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`nats:latest`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` ports`}),_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\":`#D4D4D4`},children:` - `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`4222:4222`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` routr`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` image`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`fonoster/routr-one:latest`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` depends_on`}),_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\":`#D4D4D4`},children:` - `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`nats`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` environment`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` EXTERNAL_ADDRS`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:\"${DOCKER_HOST_ADDRESS}\"})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` NATS_PUBLISHER_ENABLED`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"true\"`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` NATS_PUBLISHER_URL`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`nats://nats:4222`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` ports`}),_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\":`#D4D4D4`},children:` - `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`51908:51908`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` - `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`5060:5060`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` - `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`5060:5060/udp`})]}),`\n`]})})}),_jsx(_components.p,{children:`EdgePort reads three variables:`}),_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Variable`}),_jsx(_components.th,{children:`Purpose`}),_jsx(_components.th,{children:`Default`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`NATS_PUBLISHER_ENABLED`})}),_jsxs(_components.td,{children:[`Set to `,_jsx(_components.code,{children:`true`}),` to publish events`]}),_jsx(_components.td,{children:`Off`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`NATS_PUBLISHER_URL`})}),_jsx(_components.td,{children:`NATS server to connect to`}),_jsx(_components.td,{children:_jsx(_components.code,{children:`nats://localhost:4222`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`NATS_PUBLISHER_SUBJECT`})}),_jsx(_components.td,{children:`Prefix for every subject`}),_jsx(_components.td,{children:_jsx(_components.code,{children:`routr`})})]})]})]})]}),_jsxs(Step,{title:`Start the stack`,children:[_jsx(_components.p,{children:`Start the services. Replace the address with your own.`}),_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:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`DOCKER_HOST_ADDRESS`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`192.168.1.3`}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:` docker`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` compose`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` up`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -d`})]}),`\n`]})})}),_jsx(_components.p,{children:`Confirm that EdgePort connected to NATS.`}),_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:`docker`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` compose`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` logs`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` routr`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` |`}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:` grep`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"nats publisher\"`})]}),`\n`]})})}),_jsx(_components.p,{children:`The output includes a line that ends like this:`}),_jsx(CodeBlock,{filename:``,numberOfLines:`2`,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:`2`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`GRPCSipListener.java nats publisher enabled with subject routr and url nats://nats:4222`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),_jsx(Check,{children:_jsxs(_components.p,{children:[`The log line above appears, and the `,_jsx(_components.code,{children:`routr`}),` container stays up.`]})})]}),_jsxs(Step,{title:`Subscribe to Routr events`,children:[_jsxs(_components.p,{children:[`Create a `,_jsx(_components.code,{children:`nats`}),` CLI context for the local server and select it.`]}),_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:`nats`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` context`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` add`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` local`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --server`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` nats://localhost:4222`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --description`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"Routr events\"`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --select`})]}),`\n`]})})}),_jsxs(_components.p,{children:[`Subscribe to every subject under `,_jsx(_components.code,{children:`routr`}),`. Leave this running.`]}),_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:`nats`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` sub`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"routr.>\"`})]}),`\n`]})})}),_jsx(CodeBlock,{filename:``,numberOfLines:`2`,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:`2`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Subscribing on routr.>`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})})]}),_jsxs(Step,{title:`Create a Domain and two Agents`,children:[_jsxs(_components.p,{children:[`In another terminal, install `,_jsx(_components.code,{children:`rctl`}),`.`]}),_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:`npm`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` install`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --location=global`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` @routr/ctl`})]}),`\n`]})})}),_jsxs(_components.p,{children:[`Create a Domain with the SIP URI `,_jsx(_components.code,{children:`sip.local`}),`.`]}),_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:`rctl`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` domains`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` create`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --insecure`})]}),`\n`]})})}),_jsxs(_components.p,{children:[`Create credentials and an Agent for `,_jsx(_components.code,{children:`1001`}),`, then repeat for `,_jsx(_components.code,{children:`1002`}),`. Pick the Domain `,_jsx(_components.code,{children:`sip.local`}),` and the matching credentials when `,_jsx(_components.code,{children:`rctl agents create`}),` asks.`]}),_jsx(CodeBlock,{filename:``,numberOfLines:`2`,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:`2`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`rctl`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` credentials`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` create`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --insecure`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`rctl`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` agents`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` create`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --insecure`})]}),`\n`]})})}),_jsxs(_components.p,{children:[`The `,_jsx(_components.code,{children:`--insecure`}),` flag is required because this setup doesn’t use TLS on the API.`]})]}),_jsxs(Step,{title:`Register the softphones`,children:[_jsxs(_components.p,{children:[`Configure each softphone with one Agent: its username and password, `,_jsx(_components.code,{children:`sip.local`}),` as the domain, and your machine’s IP (for example, `,_jsx(_components.code,{children:`192.168.1.3:5060`}),`) as the outbound proxy over UDP.`]}),_jsx(_components.p,{children:`Each successful registration publishes an event.`}),_jsx(CodeBlock,{filename:``,numberOfLines:`3`,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:`3`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`[#1] Received on \"routr.endpoint.registered\"`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`{\"aor\":\"sip:1001@sip.local\",\"registeredAt\":\"2026-10-21T15:02:11.482Z\",\"expires\":600,\"extraHeaders\":{}}`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),_jsx(Check,{children:_jsxs(_components.p,{children:[`You see one `,_jsx(_components.code,{children:`routr.endpoint.registered`}),` message per softphone. Softphones re-register periodically, so more arrive over time.`]})})]}),_jsxs(Step,{title:`Make a call`,children:[_jsxs(_components.p,{children:[`From `,_jsx(_components.code,{children:`1001`}),`, call `,_jsx(_components.code,{children:`1002`}),`. When Routr forwards the INVITE, EdgePort publishes `,_jsx(_components.code,{children:`routr.call.started`}),`.`]}),_jsx(CodeBlock,{filename:``,numberOfLines:`3`,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:`3`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`[#3] Received on \"routr.call.started\"`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`{\"callId\":\"_Ax7XxHju-o7fbemWxxLww..\",\"from\":\"sip:1001@sip.local\",\"to\":\"sip:1002@sip.local\",\"startTime\":\"2026-10-21T15:03:10.111Z\",\"extraHeaders\":{}}`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),_jsxs(_components.p,{children:[`Hang up. EdgePort publishes `,_jsx(_components.code,{children:`routr.call.ended`}),` with the same `,_jsx(_components.code,{children:`callId`}),`.`]}),_jsx(CodeBlock,{filename:``,numberOfLines:`3`,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:`3`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`[#4] Received on \"routr.call.ended\"`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`{\"callId\":\"_Ax7XxHju-o7fbemWxxLww..\",\"endTime\":\"2026-10-21T15:03:55.760Z\",\"hangupCause\":\"NORMAL_CLEARING\",\"extraHeaders\":{}}`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),_jsx(Frame,{caption:`routr.call.started as shown by nats sub (captured on an earlier release, so the fields differ slightly)`,children:_jsx(OptimizedImage,{src:`https://mintcdn.com/routr-docs/iaqIipuuzAjyl_cH/images/call-events-with-nats/nats-sub-routr-call-started.png?fit=max\u0026auto=format\u0026n=iaqIipuuzAjyl_cH\u0026q=85\u0026s=b7ef2f296ebe557a07ff325e44c7d101`,alt:`Terminal running nats sub routr.call.started and receiving a JSON event with callId, from, to, and startTime`,\"data-og-width\":`880`,width:`880`,\"data-og-height\":`430`,height:`430`,\"data-path\":`images/call-events-with-nats/nats-sub-routr-call-started.png`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/routr-docs/iaqIipuuzAjyl_cH/images/call-events-with-nats/nats-sub-routr-call-started.png?w=280\u0026fit=max\u0026auto=format\u0026n=iaqIipuuzAjyl_cH\u0026q=85\u0026s=33d9b5638f08f7fd2c33a9179a177315 280w, https://mintcdn.com/routr-docs/iaqIipuuzAjyl_cH/images/call-events-with-nats/nats-sub-routr-call-started.png?w=560\u0026fit=max\u0026auto=format\u0026n=iaqIipuuzAjyl_cH\u0026q=85\u0026s=867415cf2e77ea1e89ec1462c87fa2de 560w, https://mintcdn.com/routr-docs/iaqIipuuzAjyl_cH/images/call-events-with-nats/nats-sub-routr-call-started.png?w=840\u0026fit=max\u0026auto=format\u0026n=iaqIipuuzAjyl_cH\u0026q=85\u0026s=0d94ad565988787b052400a12ae44a8a 840w, https://mintcdn.com/routr-docs/iaqIipuuzAjyl_cH/images/call-events-with-nats/nats-sub-routr-call-started.png?w=1100\u0026fit=max\u0026auto=format\u0026n=iaqIipuuzAjyl_cH\u0026q=85\u0026s=af5c78e03fb03e49d6a5731f117af3e6 1100w, https://mintcdn.com/routr-docs/iaqIipuuzAjyl_cH/images/call-events-with-nats/nats-sub-routr-call-started.png?w=1650\u0026fit=max\u0026auto=format\u0026n=iaqIipuuzAjyl_cH\u0026q=85\u0026s=878016fcc57259fb6fba406fbdcb6acf 1650w, https://mintcdn.com/routr-docs/iaqIipuuzAjyl_cH/images/call-events-with-nats/nats-sub-routr-call-started.png?w=2500\u0026fit=max\u0026auto=format\u0026n=iaqIipuuzAjyl_cH\u0026q=85\u0026s=139bb5f9e947c40f099b156bd107720b 2500w`})}),_jsx(Frame,{caption:`routr.call.ended as shown by nats sub (captured on an earlier release)`,children:_jsx(OptimizedImage,{src:`https://mintcdn.com/routr-docs/iaqIipuuzAjyl_cH/images/call-events-with-nats/nats-sub-routr-call-ended.png?fit=max\u0026auto=format\u0026n=iaqIipuuzAjyl_cH\u0026q=85\u0026s=bf11283a29b1eb7bb0df10cf11368b24`,alt:`Terminal running nats sub routr.call.ended and receiving a JSON event with callId, endTime, and hangupCause NORMAL_CLEARING`,\"data-og-width\":`880`,width:`880`,\"data-og-height\":`430`,height:`430`,\"data-path\":`images/call-events-with-nats/nats-sub-routr-call-ended.png`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/routr-docs/iaqIipuuzAjyl_cH/images/call-events-with-nats/nats-sub-routr-call-ended.png?w=280\u0026fit=max\u0026auto=format\u0026n=iaqIipuuzAjyl_cH\u0026q=85\u0026s=e6230852375371c3b57edf40e25d5386 280w, https://mintcdn.com/routr-docs/iaqIipuuzAjyl_cH/images/call-events-with-nats/nats-sub-routr-call-ended.png?w=560\u0026fit=max\u0026auto=format\u0026n=iaqIipuuzAjyl_cH\u0026q=85\u0026s=0f40658043423b5298775dab230e0807 560w, https://mintcdn.com/routr-docs/iaqIipuuzAjyl_cH/images/call-events-with-nats/nats-sub-routr-call-ended.png?w=840\u0026fit=max\u0026auto=format\u0026n=iaqIipuuzAjyl_cH\u0026q=85\u0026s=bb04fb4b78aba46165baae8d38ca6143 840w, https://mintcdn.com/routr-docs/iaqIipuuzAjyl_cH/images/call-events-with-nats/nats-sub-routr-call-ended.png?w=1100\u0026fit=max\u0026auto=format\u0026n=iaqIipuuzAjyl_cH\u0026q=85\u0026s=21bd89c7e57bbffc51be605891e4eebb 1100w, https://mintcdn.com/routr-docs/iaqIipuuzAjyl_cH/images/call-events-with-nats/nats-sub-routr-call-ended.png?w=1650\u0026fit=max\u0026auto=format\u0026n=iaqIipuuzAjyl_cH\u0026q=85\u0026s=1e2a59694a5df1227c60b7c3f2b98f81 1650w, https://mintcdn.com/routr-docs/iaqIipuuzAjyl_cH/images/call-events-with-nats/nats-sub-routr-call-ended.png?w=2500\u0026fit=max\u0026auto=format\u0026n=iaqIipuuzAjyl_cH\u0026q=85\u0026s=a0cb5f5a20de4a42141639f48de5f09b 2500w`})}),_jsx(Check,{children:_jsxs(_components.p,{children:[`For one call you see one `,_jsx(_components.code,{children:`routr.call.started`}),` and one `,_jsx(_components.code,{children:`routr.call.ended`}),`, and both carry the same `,_jsx(_components.code,{children:`callId`}),`.`]})})]})]}),`\n`,_jsx(Heading,{level:`2`,id:`event-reference`,children:`Event reference`}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Subject`}),_jsx(_components.th,{children:`Published when`}),_jsx(_components.th,{children:`Fields`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`routr.endpoint.registered`})}),_jsx(_components.td,{children:`A REGISTER succeeds`}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`aor`}),`, `,_jsx(_components.code,{children:`registeredAt`}),`, `,_jsx(_components.code,{children:`expires`}),`, `,_jsx(_components.code,{children:`extraHeaders`})]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`routr.call.started`})}),_jsx(_components.td,{children:`EdgePort forwards an INVITE`}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`callId`}),`, `,_jsx(_components.code,{children:`from`}),`, `,_jsx(_components.code,{children:`to`}),`, `,_jsx(_components.code,{children:`startTime`}),`, `,_jsx(_components.code,{children:`extraHeaders`}),`, plus any metadata the processor attached to the route`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`routr.call.ended`})}),_jsx(_components.td,{children:`A BYE or CANCEL completes, an INVITE fails with a status above 300, or a transport error drops the transaction`}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`callId`}),`, `,_jsx(_components.code,{children:`endTime`}),`, `,_jsx(_components.code,{children:`hangupCause`}),`, `,_jsx(_components.code,{children:`extraHeaders`})]})]})]})]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`extraHeaders`}),` holds every header in the message whose name starts with `,_jsx(_components.code,{children:`X-`}),`. For a list of hangup causes, see `,_jsx(_components.a,{href:`https://github.com/fonoster/routr/blob/main/mods/edgeport/src/main/java/io/routr/HangupCauses.java`,children:_jsx(_components.code,{children:`HangupCauses.java`})}),`.`]}),`\n`,_jsxs(_components.p,{children:[`To change the prefix, set `,_jsx(_components.code,{children:`NATS_PUBLISHER_SUBJECT`}),`. For example, `,_jsx(_components.code,{children:`NATS_PUBLISHER_SUBJECT=myserver`}),` publishes `,_jsx(_components.code,{children:`myserver.call.started`}),`, `,_jsx(_components.code,{children:`myserver.call.ended`}),`, and `,_jsx(_components.code,{children:`myserver.endpoint.registered`}),`.`]}),`\n`,_jsx(Tip,{children:_jsxs(_components.p,{children:[`To print events to EdgePort’s log instead of NATS while you debug, set `,_jsx(_components.code,{children:`CONSOLE_PUBLISHER_ENABLED=true`}),`.`]})}),`\n`,_jsx(Heading,{level:`2`,id:`clean-up`,children:`Clean up`}),`\n`,_jsx(_components.p,{children:`Stop and remove the containers, and delete the CLI context.`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`2`,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:`2`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`docker`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` compose`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` down`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`nats`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` context`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` rm`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` local`})]}),`\n`]})})}),`\n`,_jsx(Heading,{level:`2`,id:`next-steps`,children:`Next steps`}),`\n`,_jsxs(CardGroup,{cols:2,children:[_jsx(Card,{title:`EdgePort`,icon:`tower-broadcast`,href:`/reference/components/edgeport`,children:_jsx(_components.p,{children:`EdgePort configuration and environment variables.`})}),_jsx(Card,{title:`Environment variables`,icon:`list`,href:`/reference/environment-variables`,children:_jsx(_components.p,{children:`Every variable Routr reads, by component.`})}),_jsx(Card,{title:`SIP headers`,icon:`heading`,href:`/reference/sip-headers`,children:_jsxs(_components.p,{children:[`The `,_jsx(_components.code,{children:`X-`}),` headers Routr adds and reads.`]})}),_jsx(Card,{title:`Deploy with Docker`,icon:`docker`,href:`/guides/deploy-with-docker`,children:_jsx(_components.p,{children:`Run Routr with Docker in 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":{"codeStyling":"system","config":{},"pageMetadata":{"title":"Stream call events to NATS","sidebarTitle":"Call events with NATS","description":"Turn on EdgePort's NATS publisher, subscribe with the nats CLI, and see an event for every registration, call start, and call end.","href":"/tutorials/call-events-with-nats"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"What you’ll build","slug":"what-you’ll-build","depth":2,"children":[]},{"title":"Prerequisites","slug":"prerequisites","depth":2,"children":[]},{"title":"Steps","slug":"steps","depth":2,"children":[]},{"title":"Event reference","slug":"event-reference","depth":2,"children":[]},{"title":"Clean up","slug":"clean-up","depth":2,"children":[]},{"title":"Next steps","slug":"next-steps","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":[],"subdomain":"routr-docs","siteName":"Routr","title":"Stream call events to NATS - Routr","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-10-22T04:21:21.071Z","originalFileLocation":"tutorials/call-events-with-nats.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=\"dark\"}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=\"Turn on EdgePort\u0026#x27;s NATS publisher, subscribe with the nats CLI, and see an event for every registration, call start, and call end.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Routr\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/routr-docs/wWnXExYwxQiV3LdH/_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/routr-docs/wWnXExYwxQiV3LdH/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/routr-docs/wWnXExYwxQiV3LdH/_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/routr-docs/wWnXExYwxQiV3LdH/_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/routr-docs/wWnXExYwxQiV3LdH/_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/routr-docs/wWnXExYwxQiV3LdH/_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/routr-docs/wWnXExYwxQiV3LdH/_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/routr-docs/wWnXExYwxQiV3LdH/_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/routr-docs/wWnXExYwxQiV3LdH/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Stream call events to NATS - Routr\">\u003cmeta data-mint-head property=\"og:description\" content=\"Turn on EdgePort\u0026#x27;s NATS publisher, subscribe with the nats CLI, and see an event for every registration, call start, and call end.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Routr\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.routr.io/tutorials/call-events-with-nats\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://routr-docs.mintlify.app/_mintlify/api/og/v2?division=Tutorials\u0026amp;title=Stream+call+events+to+NATS\u0026amp;description=Turn+on+EdgePort%27s+NATS+publisher%2C+subscribe+with+the+nats+CLI%2C+and+see+an+event+for+every+registration%2C+call+start%2C+and+call+end.\u0026amp;theme=695134023fea6aad9acf78c3\u0026amp;signature=a0c80486e3eadc7652dfe80d20bb0d9c670b63c363149cf4c6b42b820ee20edb\">\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=\"Stream call events to NATS - Routr\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Turn on EdgePort\u0026#x27;s NATS publisher, subscribe with the nats CLI, and see an event for every registration, call start, and call end.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://routr-docs.mintlify.app/_mintlify/api/og/v2?division=Tutorials\u0026amp;title=Stream+call+events+to+NATS\u0026amp;description=Turn+on+EdgePort%27s+NATS+publisher%2C+subscribe+with+the+nats+CLI%2C+and+see+an+event+for+every+registration%2C+call+start%2C+and+call+end.\u0026amp;theme=695134023fea6aad9acf78c3\u0026amp;signature=a0c80486e3eadc7652dfe80d20bb0d9c670b63c363149cf4c6b42b820ee20edb\">\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/routr-docs/wWnXExYwxQiV3LdH/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Routr\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#1F8F8E\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.routr.io/tutorials/call-events-with-nats\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/tutorials/call-events-with-nats.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.routr.io/#organization\",\"name\":\"Routr\",\"url\":\"https://docs.routr.io\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/routr-docs/iaqIipuuzAjyl_cH/logo/light.svg?fit=max\u0026auto=format\u0026n=iaqIipuuzAjyl_cH\u0026q=85\u0026s=46cd1037119709d8341f90de12fdd541\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.routr.io#website\",\"name\":\"Routr\",\"url\":\"https://docs.routr.io\",\"publisher\":{\"@id\":\"https://docs.routr.io/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.routr.io/tutorials/call-events-with-nats#webpage\",\"url\":\"https://docs.routr.io/tutorials/call-events-with-nats\",\"name\":\"Stream call events to NATS\",\"description\":\"Turn on EdgePort's NATS publisher, subscribe with the nats CLI, and see an event for every registration, call start, and call end.\",\"dateModified\":\"2026-10-22T04:21:21.071Z\",\"isPartOf\":{\"@id\":\"https://docs.routr.io#website\"},\"breadcrumb\":{\"@id\":\"https://docs.routr.io/tutorials/call-events-with-nats#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.routr.io/tutorials/call-events-with-nats#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Tutorials\",\"item\":\"https://docs.routr.io/tutorials/load-balancing-asterisk\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Stream call events to NATS\",\"item\":\"https://docs.routr.io/tutorials/call-events-with-nats\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://docs.routr.io/tutorials/call-events-with-nats#article\",\"headline\":\"Stream call events to NATS\",\"name\":\"Stream call events to NATS\",\"description\":\"Turn on EdgePort's NATS publisher, subscribe with the nats CLI, and see an event for every registration, call start, and call end.\",\"url\":\"https://docs.routr.io/tutorials/call-events-with-nats\",\"mainEntityOfPage\":{\"@id\":\"https://docs.routr.io/tutorials/call-events-with-nats#webpage\"},\"dateModified\":\"2026-10-22T04:21:21.071Z\",\"publisher\":{\"@id\":\"https://docs.routr.io/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.routr.io#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Routr\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"Routr","nav":{"global":{"anchors":[{"anchor":"GitHub","icon":"github","href":"https://github.com/fonoster/routr"},{"anchor":"Community","icon":"discord","href":"https://discord.gg/4QWgSz4hTC"},{"anchor":"Previous versions","icon":"clock-rotate-left","href":"/previous-versions"}]},"tabs":[{"tab":"Docs","groups":[{"group":"Get started","pages":[{"title":"Introduction","href":"/introduction"},{"title":"Quickstart","href":"/quickstart"},{"title":"Quickstart on Kubernetes","sidebarTitle":"Quickstart (Kubernetes)","href":"/quickstart-kubernetes"}]},{"group":"Concepts","pages":[{"title":"Architecture","href":"/concepts/architecture"},{"title":"Message flow","href":"/concepts/message-flow"},{"title":"EdgePort cooperation","href":"/concepts/edgeport-cooperation"},{"title":"Connect mode","href":"/concepts/connect-mode"},{"title":"Routing","href":"/concepts/routing"},{"title":"Load balancing","href":"/concepts/load-balancing"},{"title":"Deployment topologies","href":"/concepts/deployment-topologies"}]},{"group":"How-to guides","pages":[{"group":"Deploy and operate","icon":"server","pages":[{"title":"Deploy with Docker","sidebarTitle":"Deploy with Docker","href":"/guides/deploy-with-docker"},{"title":"Deploy on Kubernetes with Helm","sidebarTitle":"Deploy on Kubernetes","href":"/guides/deploy-on-kubernetes"},{"title":"Secure the server","href":"/guides/secure-the-server"},{"title":"Scale the Location Service with Redis","sidebarTitle":"Scale with Redis","href":"/guides/scale-with-redis"}]},{"group":"Connect phones and services","icon":"phone","pages":[{"title":"Set up a home or office phone system","sidebarTitle":"Home or office setup","href":"/guides/home-or-office-setup"},{"title":"Connect Asterisk or FreeSWITCH as a Peer","sidebarTitle":"Connect a PBX as a Peer","href":"/guides/connect-a-pbx-as-a-peer"},{"title":"Enable WebRTC clients","sidebarTitle":"Enable WebRTC","href":"/guides/enable-webrtc"}]},{"group":"Manage resources","icon":"list","pages":[{"title":"Manage resources with rctl","sidebarTitle":"Manage with rctl","href":"/guides/manage-resources-with-rctl"},{"title":"Manage resources with the Node.js SDK","sidebarTitle":"Manage with the SDK","href":"/guides/manage-resources-with-the-sdk"}]},{"group":"Extend Routr","icon":"puzzle-piece","pages":[{"title":"Build a processor","sidebarTitle":"Build a processor","href":"/guides/build-a-processor"},{"title":"Build a middleware","sidebarTitle":"Build a middleware","href":"/guides/build-a-middleware"},{"title":"Store custom data with the API Server","sidebarTitle":"Custom data","href":"/guides/custom-data-with-the-apiserver"},{"title":"Extend rctl with plugins","sidebarTitle":"Extend rctl","href":"/guides/extend-rctl"}]},{"group":"Work on Routr","icon":"code","pages":[{"title":"Run Routr from source","sidebarTitle":"Run from source","href":"/guides/run-from-source"},{"title":"Develop with Gitpod","sidebarTitle":"Develop with Gitpod","href":"/guides/develop-with-gitpod"}]}]},{"group":"Tutorials","pages":[{"title":"Load balance Asterisk with Routr","sidebarTitle":"Load balance Asterisk","href":"/tutorials/load-balancing-asterisk"},{"title":"Build an intercom system on Kubernetes","sidebarTitle":"Intercom on Kubernetes","href":"/tutorials/intercom-on-kubernetes"},{"title":"Deploy Routr to Civo with Helm","sidebarTitle":"Deploy to Civo","description":"Create a Civo Kubernetes cluster, install the routr-connect chart with a public SIP address, and verify it with rctl.","href":"/tutorials/deploy-to-civo-with-helm"},{"title":"Stream call events to NATS","sidebarTitle":"Call events with NATS","href":"/tutorials/call-events-with-nats"},{"title":"Call from the browser with ephemeral agents","sidebarTitle":"Ephemeral agents in the browser","description":"Issue a signed JWT to a website visitor, register a SIP.js client with it, and call an Asterisk server through Routr and RTPEngine.","href":"/tutorials/ephemeral-agents-in-the-browser"}]},{"group":"Community","pages":[{"title":"Community","href":"/community"},{"title":"Contributing","href":"/contributing"},{"title":"Frequently asked questions","sidebarTitle":"FAQs","href":"/faqs"}]}]},{"tab":"Reference","pages":[{"title":"Reference","href":"/reference/rctl"}]},{"tab":"Changelog","pages":[{"title":"Changelog","href":"/changelog"}]}]},"title":"Stream call events to NATS - Routr","buildId":"dpl_9DauxEjb9gzCtcuhPQFbquJvx7FJ","deploymentId":"dpl_9DauxEjb9gzCtcuhPQFbquJvx7FJ","dynamics":["07c022d89b","a74be98ba7"],"chunks":["Frame-DpBmNN95.js","DynamicMarkdown-BY_qDhTn.js","zoom-image-lightbox-D4WcYaf4.js","PlusIcon-CwhPVjTe.js","lightbox-handle-r17bVUz3.js"]}