DigitalOcean serverless functions for Edge. Deployed automatically on push to
main via DigitalOcean's built-in GitHub integration.
Automatically converts Intercom leads into users whenever a lead has an email address. Listens to three webhook topics:
contact.lead.created— lead created with an emailcontact.lead.added_email— email added to a lead that had nonecontact.email.updated— lead's email changed
How it works:
- Intercom fires a webhook
- The function verifies the HMAC-SHA1 signature
- If the contact is a lead with an email:
- Searches for an existing user with that email
- Creates one if none exists
- Merges the lead into the user (lead is deleted)
- Returns 200 so Intercom does not retry
Automatically infers a caller's timezone when an inbound call starts in
Intercom. Listens to the call.started webhook topic and filters to
inbound calls only.
How it works:
- Intercom fires a
call.startedwebhook for an inbound call - The function verifies the HMAC-SHA1 signature
- Parses the caller's E.164 phone number with
phonenumbers(Google's libphonenumber) to determine country and timezone - For US/CA numbers, uses the 3-digit area code to narrow to a specific timezone
- Creates an internal note on the contact with timezone details (visible in all Inbox views)
- Sets an
inferred_timezonecustom attribute on the contact (filterable, usable in reports)
edge-serverless-functions/
├── project.yml # DO Functions config (all packages)
├── .env.example # Template for local dev secrets
├── README.md
└── packages/
└── intercom/
├── lead-to-user/ # Lead-to-user auto-converter
│ ├── __main__.py # Entry point
│ ├── intercom_client.py # Intercom API client
│ ├── requirements.txt # Python dependencies
│ └── build.sh # Dependency installer for DO
├── call-timezone/ # Inbound call timezone inference
│ ├── __main__.py # Webhook handler (call.started)
│ ├── timezone.py # Phone → timezone inference
│ ├── intercom_client.py # Note + attribute API client
│ ├── requirements.txt
│ └── build.sh
└── tests/ # Dev/test (not deployed)
├── test_webhook.py # Test suite (pytest)
├── test_payload.json # Sample webhook payload
└── serve_local.py # Local dev server (ngrok)
- Create a new package under
packages/:
packages/
└── your-package/
├── your-function/
│ ├── __main__.py
│ ├── requirements.txt
│ └── build.sh
└── tests/
└── test_your_function.py
- Add it to
project.yml:
packages:
- name: your-package
environment:
YOUR_SECRET: ${YOUR_SECRET}
functions:
- name: your-function
runtime: python:3.12
web: raw-
Add any new environment variables in the DO Functions dashboard and update
.env.example. -
Push to
main— DO automatically deploys.
Handled by DigitalOcean's built-in GitHub integration. When code is
pushed/merged to main, DO automatically rebuilds and deploys all functions.
Set these in the DO Functions dashboard:
| Variable | Description |
|---|---|
INTERCOM_ACCESS_TOKEN |
Intercom API bearer token |
WEBHOOK_SECRET |
Intercom app client secret |
If you need to deploy without the GitHub integration:
doctl auth init
doctl serverless connect
cp .env.example .env # fill in real values
doctl serverless deploy . --remote-build
doctl serverless functions get intercom/lead-to-user --urlpip install pytest requests
pytest packages/intercom/tests/test_webhook.py -vcp .env.example .env
# Fill in real credentials
pip install requests python-dotenv
python3 packages/intercom/tests/serve_local.py
# In another terminal:
ngrok http 8080
# Copy the ngrok URL into Intercom webhook settings