Skip to content

sciencebased/hotmart-webhook

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

hotmart-webhook

AWS Lambda that receives Hotmart postback events and forwards them to a Discord channel as a clean, human-readable embed.

Why this exists

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.

Architecture

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 an x-hotmart-hottok header 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.

Files

  • lambda_function.py — the handler. Entry point is lambda_handler.
  • trust-policy.json — IAM trust policy granting lambda.amazonaws.com permission 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.

Prerequisites

  • 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).
  • zip and bash available locally.

Deploy

export DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/XXXXX/YYYYY"
./deploy.sh

Optional 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.

Updating

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).

Local testing

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.

Tailing logs

aws logs tail /aws/lambda/hotmart-webhook --follow

Each 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.

Hardening ideas (not yet implemented)

  • Validate x-hotmart-hottok against a HOTMART_HOTTOK env var and reject mismatches (Hotmart guarantees this header on every postback).
  • Add aws lambda add-permission scoped to Hotmart's source IP ranges instead of Principal=*.
  • Use AWS Secrets Manager for DISCORD_WEBHOOK_URL instead of plain env var.

About

HOTMART <-> DISCORD integration webhook

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors