AWS Lambda that receives Hotmart postback events and forwards them to a Discord channel as a clean, human-readable embed.
Hotmart can send postback notifications (purchases, refunds, subscription changes, etc.) to any HTTPS endpoint. Their payloads are verbose and not friendly to read directly in a chat channel. This service:
- Exposes a public HTTPS endpoint via a Lambda Function URL (no API Gateway needed).
- Parses Hotmart payloads in both formats:
- JSON v2 (current Hotmart API — what's actually sent today).
- Legacy form-urlencoded (older postback 1.x).
- Normalizes the data and posts a structured embed to a Discord webhook with the fields that matter: customer, document, phone, product, price, payment, transaction, status, address, producer, affiliate, coupon.
- Colors the embed by event type (green for approved/complete, red for chargeback/refund/cancel, yellow for pending, etc.).
The result is a single readable card in Discord per Hotmart event, instead of raw JSON or form data.
Hotmart ──POST──▶ Lambda Function URL ──▶ lambda_function.lambda_handler
│
└──POST embed──▶ Discord webhook
- Runtime: Python 3.12, standard library only (no dependencies, no build step beyond zipping the source).
- Auth: Function URL is
AuthType=NONE(public). Hotmart includes anx-hotmart-hottokheader that can be validated against a shared secret if you want to harden it — currently not enforced. - Logs: CloudWatch group
/aws/lambda/<function-name>. The handler prints the raw incoming event and the normalized payload for debugging.
lambda_function.py— the handler. Entry point islambda_handler.trust-policy.json— IAM trust policy grantinglambda.amazonaws.compermission to assume the execution role.deploy.sh— idempotent deploy script. Creates the IAM role, Lambda function, and Function URL on first run; updates the code and environment on subsequent runs.
- AWS CLI configured with credentials that can create IAM roles, Lambda functions, and Function URLs.
- A Discord webhook URL (Server Settings → Integrations → Webhooks → New Webhook).
zipandbashavailable locally.
export DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/XXXXX/YYYYY"
./deploy.shOptional environment overrides:
| Variable | Default | Purpose |
|---|---|---|
FUNCTION_NAME |
hotmart-webhook |
Lambda function name. |
ROLE_NAME |
hotmart-webhook-role |
IAM execution role name. |
AWS_REGION |
us-east-1 |
Deployment region. |
RUNTIME |
python3.12 |
Lambda runtime. |
TIMEOUT |
15 |
Function timeout in seconds. |
MEMORY |
256 |
Memory in MB. |
The script prints the public Function URL at the end. Use that URL as the Postback URL in your Hotmart product configuration.
To change the Discord webhook without redeploying code:
aws lambda update-function-configuration \
--function-name hotmart-webhook \
--environment "Variables={DISCORD_WEBHOOK_URL=NEW_URL}"To redeploy after editing lambda_function.py, just run ./deploy.sh again (it detects the existing function and runs update-function-code).
Send a sample JSON v2 payload to the deployed URL:
curl -X POST <FUNCTION_URL> \
-H "Content-Type: application/json" \
-d '{"event":"PURCHASE_COMPLETE","data":{"buyer":{"name":"Test","email":"t@example.com","document":"123","document_type":"CPF"},"product":{"name":"Test product","id":1},"purchase":{"transaction":"HP123","status":"COMPLETED","price":{"value":100,"currency_value":"USD"},"payment":{"type":"CREDIT_CARD","installments_number":1}}}}'You should see {"forwarded": true} in the response and a new embed in Discord.
aws logs tail /aws/lambda/hotmart-webhook --followEach invocation prints:
INCOMING EVENT: ...— raw Lambda event including headers and body.NORMALIZED (json|form): ...— the parsed/normalized dict used to build the embed.Forwarded event=<name> transaction=<id> discord_status=<code>— on success.
- Validate
x-hotmart-hottokagainst aHOTMART_HOTTOKenv var and reject mismatches (Hotmart guarantees this header on every postback). - Add
aws lambda add-permissionscoped to Hotmart's source IP ranges instead ofPrincipal=*. - Use AWS Secrets Manager for
DISCORD_WEBHOOK_URLinstead of plain env var.