- language:python - language:php - language:nodejs - sdk:compatibility - product:voice # Handling Calls from Code In [Making and Receiving Phone Calls](/voice/getting-started/making-and-receiving-phone-calls) we learned how to use Compatibility XML bins to control outbound and inbound calls. In particular, we showed how to play a simple audio message. Handling calls from code gives us more flexibility. Instead of serving a static XML bin, we can use a custom web server to decide the content of the XML depending on the state of the call, on the caller, on the time, etc. In this guide, we will show how to create a simple phone service which will tell the user the current day, with a variation on weekends. ## Setting up the environment We are going to use a few libraries to make our job easier. In particular, well need the SignalWire Compatibility SDK and, depending on the language youre using, well also need a web server. Lets install them: import Tabs from @theme/Tabs; import TabItem from @theme/TabItem; shell pip install flask signalwire shell composer require signalwire-community/signalwire shell npm install express @signalwire/compatibility-api ## Producing XML Wed like to set up an endpoint (our own dynamic XML bin) which emits an XML document, like this one: xml Welcome! Today is Friday. The XML will be sent back to the client as a response to their request. In principle, we could manually create such XML by means of string concatenation or interpolation. However, if you are using one of our supported languages, you can use our libraries to more easily produce the same XML: python from twilio.twiml.voice_response import VoiceResponse response = VoiceResponse() response.say(Welcome! Today is Friday.) # Prints the XML string. print(response.to_xml()) php say(Welcome! Today is Friday.); # Prints the XML string. echo $response->asXML(); javascript import { RestClient } from @signalwire/compatibility-api; const response = new RestClient.LaML.VoiceResponse(); response.say(Welcome! Today is Friday.); // Prints the XML string. console.log(response.toString()); ## Serving the XML Now that we know how to generate a proper Compatibility XML document, lets see how to set up a web server to serve those documents. ### Setting up a web server How you set up the web server is mostly specific to the language and framework of your choosing. A basic skeleton might be the following: python title=main.py from flask import Flask, request, Response from twilio.twiml.voice_response import VoiceResponse app = Flask(__name__) @app.route(/, methods=[GET, POST]) def call_handler(): This endpoint will be queried by SignalWire whenever an incoming call is received. We respond with an XML document which specifies the next instructions. print(request.values) # The logic goes here return php title=index.php javascript title=index.js import express from express; import { RestClient } from @signalwire/compatibility-api; const app = express(); app.use(express.urlencoded({ extended: true })); /** * @param {express.Request} req * @param {express.Response} res */ function callHandler(req, res) { // This endpoint will be queried by SignalWire whenever an incoming call is received. // We respond with an XML document which specifies the next instructions. console.log(req.body); // The logic goes here. } app.get(/, callHandler); app.post(/, callHandler); app.listen(8080); In the next section we will configure a phone number so that, when it receives a message, SignalWire makes an HTTP request to our message handler endpoint. The HTTP request will contain as parameters values such as the source number or the body of the incoming message. For our simple subscription service demo, our message handler needs to look at the body of the message to determine whether it contains the word START or STOP. Depending on the word, we will emit an XML document which will produce different messages. python title=main.py from flask import Flask, request, Response from twilio.twiml.voice_response import VoiceResponse from datetime import datetime app = Flask(__name__) @app.route(/, methods=[GET, POST]) def call_handler(): This endpoint will be queried by SignalWire whenever an incoming call is received. We respond with an XML document which specifies the next instructions. print(request.values) # Get the callers number caller = request.values.get(From) now = datetime.now() response = VoiceResponse() response.say(fWelcome! Today is {now.strftime(%A)}.) response.say(fYour phone number ends in {caller[-2:]}.) if now.weekday() >= 5: response.say(fEnjoy the weekend.) return Response(response.to_xml(), mimetype=text/xml) php title=index.php say(Welcome! Today is . date(l)); $response->say(Your phone number ends in . substr($caller, -2)); if (date(w) == 0 || date(w) == 6) { $response->say(Enjoy the weekend.); } header(Content-type: text/xml); echo $response->asXML(); javascript title=index.js import express from express; import { RestClient } from @signalwire/compatibility-api; const app = express(); app.use(express.urlencoded({ extended: true })); /** * @param {express.Request} req * @param {express.Response} res */ function callHandler(req, res) { // This endpoint will be queried by SignalWire whenever an incoming call is received. // We respond with an XML document which specifies the next instructions. /** @type string */ const caller = req.body?.[From] ?? ; const now = new Date(); const response = new RestClient.LaML.VoiceResponse(); response.say(Welcome! Today is + now.toLocaleString(en-us, { weekday: long })); response.say(Your phone number ends in + caller.slice(-2)); if (now.getDay() === 0 || now.getDay() === 6) { response.say(Enjoy the weekend.); } res.set(Content-Type, text/xml); res.send(response.toString()); } app.get(/, callHandler); app.post(/, callHandler); app.listen(8080); This simple message handler works like a dynamic XML bin, whose content depends on the received message. Try running the application, which will listen on port 8080: bash python3 -m flask --app main.py run --host=0.0.0.0 --port 8080 bash docker run --rm -it -p 8080:80 -v $PWD:/var/www/html php:8.1-apache bash node index.js Since you are likely behind a NAT, to test this application on your local machine you need a public IP address that SignalWire can reach. We suggest using [ngrok](https://ngrok.com/): refer to our [guide on ngrok](/platform/basics/guides/technical-troubleshooting/how-to-test-webhooks-with-ngrok) for more information. In short, while the application is up and listening on port 8080, run ngrok from a new terminal like this: bash ngrok http 8080 Youll get a public random URL (such as https://983f-93-41-16-193.ngrok.io/) that you can use to access your local application. ### Configuring the number Now that the code is ready and the HTTP endpoint is reachable from the web, we need to configure our SignalWire number to access it. If you dont have a phone number yet, make sure to [buy one](/platform/phone-numbers/getting-started/buying-a-phone-number). You will need at least one number to receive messages. Then, open the settings for the number. Under Voice and Fax Settings, choose to handle incoming calls using LaML Webhooks, then paste the public ngrok URL which connects to your application. Connecting a number to your XML endpoint. First select LaML Webhooks, then paste the URL of the bin. Try dialing the configured phone number: after a few seconds youll receive an automated reply, whose content will be different depending on the day of the week. ## Conclusion We have shown how to handle calls from code, by emitting XML documents whose content depends on external factors. We did all this in the context of the [Compatibility API](/compatibility-api). For more advanced, real-time applications, youll want to check out our [Realtime SDK](/sdks/reference/realtime-sdk/relay-v4). Find more details in the guide about [First Steps with Voice in the Realtime SDK](/sdks/reference/realtime-sdk/guides/voice/first-steps-with-voice).