UPDATE def_webhook
SET Buildoutputvalidation = 'Y'
WHERE WebhookCode = 'YOUR_WEBHOOK_CODE';
UPDATE def_webhook_parameters
SET Required = 'Y'
WHERE WebhookCode = 'YOUR_WEBHOOK_CODE'
AND PostType = 'RETURN'
AND Parameter IN ('customer_id', 'order_id', 'status');
INSERT INTO def_webhook_output_validations (
WebhookCode,
Package,
Description,
Rank,
ValidationSql,
ValidationNote,
Active
) VALUES (
'YOUR_WEBHOOK_CODE',
'YOUR_PACKAGE',
'Validation description',
1,
'SELECT IF(condition, "Y", "N")',
'Error message shown to client',
'Y'
);
-- Validate customer_id exists
ValidationSql:
SELECT IF(
EXISTS(SELECT 1 FROM customers WHERE id = $customer_id$),
'Y',
'N'
)
ValidationNote: 'Customer ID not found'
-- Validate amount is between 100 and 1,000,000
ValidationSql:
SELECT IF(
$total_amount$ BETWEEN 100 AND 1000000,
'Y',
'N'
)
ValidationNote: 'Amount must be between R100 and R1,000,000'
-- Validate status is in allowed list
ValidationSql:
SELECT IF(
$status$ IN ('PENDING', 'APPROVED', 'REJECTED'),
'Y',
'N'
)
ValidationNote: 'Invalid status value'
-- Validate order belongs to customer
ValidationSql:
SELECT IF(
EXISTS(
SELECT 1 FROM orders
WHERE order_id = $order_id$
AND customer_id = $customer_id$
),
'Y',
'N'
)
ValidationNote: 'Order does not belong to customer'
-- Validate total = subtotal + tax
ValidationSql:
SELECT IF(
ABS($total$ - ($subtotal$ + $tax$)) < 0.01,
'Y',
'N'
)
ValidationNote: 'Total amount calculation error'
-- Validate credit score requirements
ValidationSql:
SELECT IF(
$credit_score$ >= 600 OR $down_payment$ >= 0.20 * $loan_amount$,
'Y',
'N'
)
ValidationNote: 'Credit score too low or insufficient down payment'
from factory.web.WebHooks import WebHooks
hook = WebHooks()
hook.Read('YOUR_WEBHOOK_CODE')
# Valid payload
payload = '{"customer_id": "12345", "amount": "500.00"}'
hook.set_payload(payload, 'JSON')
hook.token = 'your-api-token'
hook.commit()
results, status = hook.RenderResult()
print(f"Status: {status}") # Should be 200
print(f"Result: {results}")
# Missing required field
payload = '{"amount": "500.00"}' # customer_id missing
hook.set_payload(payload, 'JSON')
hook.commit()
results, status = hook.RenderResult()
print(f"Status: {status}") # Should be 400
print(f"Error: {results['result_note']}")
# "Required output fields missing: customer_id"
Check:
SELECT Buildoutputvalidation
FROM def_webhook
WHERE WebhookCode = 'YOUR_WEBHOOK_CODE';
Fix: Set to 'Y'
Check:
SELECT * FROM def_webhook_output_validations
WHERE WebhookCode = 'YOUR_WEBHOOK_CODE'
AND Active = 'Y';
Fix: Ensure validation rules exist and Active = 'Y'
Check: Parameter name case must match
-- Output parameter is 'customer_id' (lowercase)
-- Use: $customer_id$
-- Not: $Customer_Id$ or $CUSTOMER_ID$
Check:
SELECT Parameter, ValueType, Required
FROM def_webhook_parameters
WHERE WebhookCode = 'YOUR_WEBHOOK_CODE'
AND PostType = 'RETURN';
Fix: Ensure ValueType matches actual data (INT/FLOAT/JSON/STRING)
| Syntax | Source | Example |
|---|---|---|
$guid$ |
Webhook execution GUID | abc123-def456... |
$customer_id$ |
Output (self.results) | 12345 |
$email$ |
Input (self.params) | user@example.com |
$date$ |
System variable | 2026-02-19 |
$package$ |
Active package | homechoice |
Validation SQL:
SELECT IF(
EXISTS(
SELECT 1 FROM orders
WHERE order_id = $order_id$
AND customer_id = $customer_id$
AND status = 'ACTIVE'
),
'Y',
'N'
)
After substitution:
SELECT IF(
EXISTS(
SELECT 1 FROM orders
WHERE order_id = 'ORD-12345'
AND customer_id = '98765'
AND status = 'ACTIVE'
),
'Y',
'N'
)
{
"customer_id": "12345",
"order_id": "ORD-98765",
"status": "APPROVED",
"result": "Success",
"Statuscode": 200
}
{
"result": "Error",
"result_note": "Required output fields missing: customer_id, order_id",
"Statuscode": 400
}
{
"result": "Error",
"result_note": "Output type validation failed: customer_id must be integer",
"Statuscode": 400
}
{
"result": "Error",
"result_note": "Output validation failure: Customer ID not found; Amount exceeds limit",
"Statuscode": 400
}
-- Begin with required field validation
UPDATE def_webhook_parameters
SET Required = 'Y'
WHERE Parameter = 'critical_field';
-- Add custom validations incrementally
-- Good
ValidationNote: 'Customer ID not found in database'
-- Bad
ValidationNote: 'Validation failed'
-- Critical validations first (higher Rank)
Rank = 100: Verify customer exists
Rank = 90: Verify account is active
Rank = 80: Verify sufficient credit
Rank = 10: Verify optional metadata
-- Good - simple and fast
SELECT IF(EXISTS(SELECT 1 FROM customers WHERE id = $id$), 'Y', 'N')
-- Avoid - complex query
SELECT IF(
(SELECT COUNT(*) FROM (
SELECT * FROM orders o
JOIN customers c ON ...
JOIN products p ON ...
WHERE ...
) subquery) > 0,
'Y',
'N'
)
# Enable debug mode
DO_DEBUG = True
# Run webhook test
python factory.web/WebHooks.py test YOUR_WEBHOOK_CODE
# Check output for validation execution
UPDATE def_webhook_output_validations
SET Active = 'N'
WHERE WebhookCode = 'YOUR_WEBHOOK_CODE'
AND Description = 'Check customer credit';
UPDATE def_webhook
SET Buildoutputvalidation = 'N'
WHERE WebhookCode = 'YOUR_WEBHOOK_CODE';
UPDATE def_webhook_output_validations
SET Active = 'Y'
WHERE WebhookCode = 'YOUR_WEBHOOK_CODE';
UPDATE def_webhook
SET Buildoutputvalidation = 'Y'
WHERE WebhookCode = 'YOUR_WEBHOOK_CODE';
SELECT
WebhookCode,
Description,
Rank,
Active,
LEFT(ValidationSql, 100) AS ValidationPreview
FROM def_webhook_output_validations
WHERE WebhookCode = 'YOUR_WEBHOOK_CODE'
ORDER BY Rank DESC;
SELECT Parameter, ValueType, Example
FROM def_webhook_parameters
WHERE WebhookCode = 'YOUR_WEBHOOK_CODE'
AND PostType = 'RETURN'
AND Required = 'Y'
ORDER BY Rank;
SELECT
WebhookCode,
Buildoutputvalidation,
Buildvalidation
FROM def_webhook
WHERE WebhookCode = 'YOUR_WEBHOOK_CODE';
Index validation queries:
-- Ensure columns used in validation SQL are indexed
CREATE INDEX idx_customer_id ON customers(id);
Use EXISTS instead of COUNT:
-- Fast
SELECT IF(EXISTS(SELECT 1 FROM table WHERE ...), 'Y', 'N')
-- Slow
SELECT IF((SELECT COUNT(*) FROM table WHERE ...) > 0, 'Y', 'N')
Limit validation scope:
-- Add LIMIT 1 when checking existence
SELECT IF(EXISTS(
SELECT 1 FROM table WHERE ... LIMIT 1
), 'Y', 'N')
Monitor slow validations:
-- Check webhook execution times
SELECT AVG(TIMESTAMPDIFF(SECOND, TimeStarted, TimeCompleted))
FROM stage_webhook
WHERE WebhookCode = 'YOUR_WEBHOOK_CODE';