Hipcall

Hipcall Developers Knowledgebase / Use Cases

Place Calls by Order Number Without Seeing the Customer's Phone Number

Learn how to let couriers call customers using an order code alone, without ever having access to the customer's phone number.

Updated October 14, 2026
Read 8 min
On this page

Overview

In delivery and logistics, couriers occasionally need to call customers — but sharing customers' phone numbers with field staff creates privacy and personal data protection problems. A customer's number should never leave your system.

This guide shows how to connect calls using an order number alone, by using Speed Dial together with a Python web service. The courier dials a short extension and enters the order code, and Hipcall automatically sets up the connection with the customer without the courier ever seeing the customer's phone number.

How it works

The courier dials the speed dial extension and enters the order number as instructed by the voice announcement. Hipcall POSTs the entered digits to your server; your server finds the customer's phone number and returns it. Hipcall places the call on the courier's behalf — the number stays hidden from start to finish.

Architecture

flowchart TD
    A[Courier dials the Speed Dial extension] --> B[Hipcall plays the intro announcement]
    B --> C[Courier enters the order number e.g. 1234]
    C --> D[Hipcall POSTs the entered code to your server]
    D --> E{Order found?}
    E -- Yes --> F[Return the customer's phone number]
    E -- No --> G[Return an error]
    F --> H[Hipcall connects the call\ncourier ↔ customer]

Step 1: Create a speed dial entry in Hipcall

  1. In the Hipcall panel, go to Settings → Developer → Speed Dial and click the New button.
  2. Enter the following settings:
    | Field | Value |
    |---|---|
    | Name | Order Call |
    | Extension number | 72 (or any available extension) |
    | URL | https://xxxx.ngrok-free.app/hizli-arama |
    | Web service authentication | Optional — if you check it, enter a Username and Password |

Also upload two announcements:

  • Intro announcement: "Please enter the order number."
  • Error announcement: The audio file played when the service fails.

Local development: Use ngrok to expose your local server. Run the ngrok http 5090 command and paste the generated HTTPS address into the URL field.

Step 2: Route the phone number to the speed dial

Creating the speed dial entry is not enough on its own. For incoming calls to reach this entry, you need to route a number to it:

  1. Go to Settings → Phone System → Phone Numbers.
  2. Select the number you want to route to the speed dial.
  3. Switch to the Business Hours tab.
  4. In the Business hours target field, select the speed dial extension number you created.

Step 3: Understand the incoming request

After the courier finishes entering digits, Hipcall sends a POST request with the following structure to your web service URL:

{
"timestamp": 1791891730,
"number": "1234",
"uuid": "e785****-****-****-****-********87e5",
"user_id": null,
"speed_dial_id": 19
}

Request fields

Field Type Description
timestamp integer Unix timestamp of the request.
number string The DTMF digits entered by the courier — your order code.
uuid string Unique ID of the call.
user_id integer / null ID of the user who started the call. Can be null if the call comes in over an external line.
speed_dial_id integer ID of the speed dial entry that was triggered.

If you enabled authentication, Hipcall sends the value Basic <Base64> in the request's Authorization header:

Authorization: Basic ZmFu****OmZh****MDM=

Step 4: Look up the order and return the destination

Query your database using the order code. If it is found, return the customer's phone number in the destination field. Hipcall connects the call to that number immediately.

Successful response:

{ "destination": "90530XXXXXXX" }

Return the phone number with its area code, as a string made up of digits and nothing else (e.g. 90530XXXXXXX).

Not found / error response:

{ "error": "Sipariş bulunamadı" }

If the order code does not exist or an error occurs, return an HTTP status code other than 200 (e.g. 404, 500). Hipcall plays the error announcement to the courier.

Step 5: The Python web service

The following Python script uses the standard library alone — it needs no extra dependencies. It supports multiple test scenarios and logs all requests coming from Hipcall.

#!/usr/bin/env python3
"""
Test service for Hipcall speed dial (Python standard library alone).
Run:
DESTINATION=90530XXXXXXX python3 hizli_arama_test_servisi.py
Optional environment variables:
DESTINATION Test number to call (default: 90530XXXXXXX)
BASIC_USER Basic Auth username (checked if both are provided)
BASIC_PASS Basic Auth password
PORT Port to listen on (default: 5090)
The scenario is chosen by the END of the web service URL you enter in the
Hipcall panel (example: https://xxxx.ngrok-free.app/hizli-arama/hata):
.../hizli-arama -> 200 + valid destination
.../hizli-arama/hata -> 500
.../hizli-arama/bozuk-json -> 200 but the body is invalid JSON
.../hizli-arama/gecersiz-numara -> 200 + destination: "3ASDASDF"
.../hizli-arama/yavas -> waits 5 s, then a valid response (3 s timeout test)
"""
import base64
import json
import os
import time
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
DESTINATION = os.environ.get("DESTINATION", "90530XXXXXXX")
BASIC_USER = os.environ.get("BASIC_USER")
BASIC_PASS = os.environ.get("BASIC_PASS")
PORT = int(os.environ.get("PORT", "5090"))
class Handler(BaseHTTPRequestHandler):
def _send(self, status, body, content_type="application/json"):
data = body.encode("utf-8")
self.send_response(status)
self.send_header("Content-Type", content_type)
self.send_header("Content-Length", str(len(data)))
self.end_headers()
self.wfile.write(data)
print(f"<-- {status} {body}\n")
def do_POST(self):
raw = self.rfile.read(
int(self.headers.get("Content-Length", 0))
).decode("utf-8", "replace")
print(f"--> POST {self.path}")
print(f" Content-Type : {self.headers.get('Content-Type')}")
print(f" Authorization: {self.headers.get('Authorization')}")
print(f" Ham gövde : {raw}")
try:
payload = json.loads(raw)
for key, value in payload.items():
print(f" {key:<10} = {value!r} ({type(value).__name__})")
except ValueError as e:
print(f" UYARI: Gelen gövde geçerli JSON değil: {e}")
# Basic Auth check
if BASIC_USER and BASIC_PASS:
expected = "Basic " + base64.b64encode(
f"{BASIC_USER}:{BASIC_PASS}".encode()
).decode()
if self.headers.get("Authorization") != expected:
return self._send(401, '{"error": "unauthorized"}')
# Choose the scenario based on the last segment of the URL
path = self.path.split("?")[0].rstrip("/")
if path.endswith("/hata"):
return self._send(500, '{"error": "test hatasi"}')
if path.endswith("/bozuk-json"):
return self._send(200, '{"destination": ')
if path.endswith("/gecersiz-numara"):
return self._send(200, json.dumps({"destination": "3ASDASDF"}))
if path.endswith("/yavas"):
time.sleep(5)
self._send(200, json.dumps({"destination": DESTINATION}))
if __name__ == "__main__":
print(f"Test servisi :{PORT} portunda çalışıyor. Aranacak numara: {DESTINATION}\n")
ThreadingHTTPServer(("0.0.0.0", PORT), Handler).serve_forever()

To start the service:

DESTINATION=90530XXXXXXX python3 hizli_arama_test_servisi.py

Then expose it with ngrok:

ngrok http 5090

Paste the HTTPS address ngrok gives you into the URL field of the Hipcall speed dial entry (e.g. https://xxxx.ngrok-free.app/hizli-arama).

Test scenarios

The service simulates different scenarios based on the last segment of the URL. You can test each scenario by changing the web service URL in the Hipcall panel:

URL ending HTTP status Behavior
/hizli-arama 200 Returns a valid destination; the call is connected.
/hizli-arama/hata 500 Returns a server error; Hipcall plays the error announcement.
/hizli-arama/bozuk-json 200 Returns an invalid JSON body; Hipcall cannot parse it.
/hizli-arama/gecersiz-numara 200 Returns 3ASDASDF as destination, which is not a number that can be dialed.
/hizli-arama/yavas 200 Waits 5 seconds; Hipcall runs into its 3-second timeout.

Full call flow: Terminal output

Below is the sequence of requests that reach your server during a real call. Hipcall first sends the webhook events, then the speed dial query:

1) call_init webhook event — Call started:

--> POST /hipcall/events/whsec_live_XXXXXXXXXXXXXXXX
Content-Type : application/json
Ham gövde : {"data":{...,"caller_number":"+90551XXXXXXX",
"callee_number":"+90850XXXXXXX",
"uuid":"e785****-****-****-****-********87e5",
"direction":"inbound",
"call_flow":[{"action":"init",
"detail":{"id":19,"type":"speed_dial"},
"timestamp":1791891724}],...},
"event":"call_init"}
<-- 200

2) Speed dial query — The courier entered the digits:

--> POST /hizli-arama
Content-Type : application/json
Authorization: Basic ZmFu****OmZh****MDM=
Ham gövde : {"timestamp":1791891730,"number":"1234",
"uuid":"e785****-****-****-****-********87e5",
"user_id":null,"speed_dial_id":19}
<-- 200 {"destination": "90530XXXXXXX"}

3) call_bridged webhook event — Call connected:

--> POST /hipcall/events/whsec_live_XXXXXXXXXXXXXXXX
Ham gövde : {"data":{...,"call_flow":[
{"action":"bridge",...},
{"action":"route",...},
{"action":"init","detail":{"id":19,"type":"speed_dial"},...}
],...},"event":"call_bridged"}
<-- 200

4) call_hangup webhook event — Call ended:

--> POST /hipcall/events/whsec_live_XXXXXXXXXXXXXXXX
Ham gövde : {"data":{...,"call_duration":39,
"has_recording":true,
"record_url":"https://storage.hipcall.com.tr/recordings/...",
"hangup_by":"user",
"call_flow":[
{"action":"hangup","detail":{"hangup_by":"user"},...},
{"action":"bridge",...},
{"action":"route",...},
{"action":"init","detail":{"id":19,"type":"speed_dial"},...}
],...},"event":"call_hangup"}
<-- 200

Tools used

Tool Purpose
Speed Dial Asks the courier for digit input and calls your web service endpoint.
Webhook Notifies your server of call lifecycle events (call_init, call_bridged, call_hangup).

Next steps

  • Speed Dial documentation — Configure extensions, announcements, and web service integration.
  • Secure your web service endpoint with Basic Auth (check the Web service authentication option in the Hipcall panel).
  • Log call records using the record_url and call_duration fields in the call_hangup event.
  • Share your questions on the Hipcall Community platform.

Was this article helpful?

Still need help?

Can't find what you're looking for? Reach out and we'll help.