Django webhook service for the Primest onboarding dev task: receive lead payloads, apply customer filters (zipcode 66*** + owner=="Ja"), validate attributes via customer mapping, and forward eligible leads to the customer receive API.
- Receive leads via POST request to
/webhook/lead/ - Filter by region (postal code 66***)
- Filter by property ownership status
- Validate and normalize attributes using
customer_attribute_mapping.json - Forward valid leads to external API
- Python 3.10+
- Django (any recent 4.x/5.x)
- requests
cd primest_task
# Create virtual environment
python -m venv .venv
source .venv/bin/activate # Linux/macOS
# or .venv\Scripts\activate # Windows
# Install dependencies
pip install -r requirements.txtEnvironment variables (can be set in .env or exported):
| Variable | Description | Default |
|---|---|---|
CUSTOMER_TOKEN |
Bearer token for external API authorization | FakeCustomerToken |
RECEIVE_URL |
URL for lead forwarding | https://contactapi.static.fyi/lead/receive/fake/daryna/ |
PRODUCT_NAME |
Product name | solar |
CUSTOMER_ATTRIBUTE_MAPPING |
Absolute path to mapping file (optional override). If unset, the app expects customer_attribute_mapping.json next to manage.py. |
(optional) |
python manage.py runserver 8000Start a tunnel so the external trigger service can reach your local webhook:
ngrok http 8000Copy the generated HTTPS URL and use it as:
https://<your-ngrok-subdomain>.ngrok-free.dev/webhook/lead/
Note: ngrok may require an account + authtoken depending on your setup.
Use the provided trigger endpoint to send a random solar lead to your webhook URL:
curl -X POST "https://contactapi.static.fyi/lead/trigger/fake/daryna/" \
-H "Authorization: Bearer FakeCustomerToken" \
-H "Content-Type: application/json" \
-d '{"url":"https://<your-ngrok-subdomain>.ngrok-free.dev/webhook/lead/"}'You can inspect incoming requests via the ngrok inspector UI:
http://127.0.0.1:4040
Accepts JSON with lead data.
Request example:
{
"zipcode": "66111",
"phone": "+49123456789",
"email": "test@example.com",
"first_name": "Max",
"last_name": "Mustermann",
"street": "Hauptstraße 1",
"city": "Saarbrücken",
"questions": {
"Sind Sie Eigentümer der Immobilie?": "Ja",
"Welche Dachform haben Sie auf Ihrem Haus?": "Satteldach",
"Wie hoch schätzen Sie Ihren Stromverbrauch?": "3500"
}
}Responses:
{"status": "forwarded", ...}— lead successfully forwarded{"status": "rejected", "reason": "..."}— lead rejected (failed filters){"status": "forward_failed", "reason": "..."}— forwarding errordropped_attrs— attributes removed because they are unknown/invalid percustomer_attribute_mapping.json(e.g., value not in allowed dropdown list).
- Postal code must start with
66 - Answer to "Sind Sie Eigentümer der Immobilie?" must be
Ja
- Only eligible leads are forwarded:
zipcodemust start with66and the answer to "Sind Sie Eigentümer der Immobilie?" must beJa. - Attribute validation follows the provided
customer_attribute_mapping.json. Invalid attributes are dropped and reported viadropped_attrs, while the lead is still forwarded. product.nameis required by the customer API. This implementation usesPRODUCT_NAME(default:solar).
primest_task/
├── leads/
│ ├── views.py # Main webhook logic
│ └── ...
├── primest_task/
│ ├── settings.py # Django settings
│ └── urls.py # URL routes
├── customer_attribute_mapping.json # Attribute mapping
├── manage.py
└── requirements.txt
- 400 from trigger / DisallowedHost: ensure
ALLOWED_HOSTSinsettings.pyallows your ngrok domain (e.g..ngrok-free.dev). - 500 FileNotFoundError (mapping): place
customer_attribute_mapping.jsonnext tomanage.pyor setCUSTOMER_ATTRIBUTE_MAPPINGto an absolute path.
MIT