A serverless AWS Lambda function that sends structured notifications to Telegram using TypeScript and the Serverless Framework.
- π AWS Lambda function with API Gateway integration
- π± Telegram Bot API integration for notifications
- π― TypeScript with strict typing
- π Structured notification format with different severity levels
- π§ Environment-based configuration
- β‘ Fast deployment with esbuild bundling
βββ src/
β βββ telegram-notification-service.ts # Telegram service class
β βββ handler.ts # Lambda handler
βββ serverless.yml # Serverless configuration
βββ package.json # Dependencies and scripts
βββ tsconfig.json # TypeScript configuration
βββ build.mjs # Build script
pnpm install-
Create a Telegram Bot:
- Message @BotFather on Telegram
- Send
/newbotcommand - Follow the instructions to create your bot
- Save the Bot Token provided
-
Get Chat ID:
- Add your bot to a chat or send a direct message
- Send a test message to your bot
- Visit:
https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getUpdates - Find your chat ID in the response (it's the
idfield in thechatobject)
Create a .env file in the project root:
BOT_TOKEN=your_telegram_bot_token_here
CHAT_ID=your_chat_id_here
REQUEST_TOKEN=your_secure_token_hereYou can generate a secure token using:
openssl rand -hex 32Set the output as your REQUEST_TOKEN value.
Important: Make sure your .env file is in .gitignore to avoid committing sensitive data.
# Deploy to AWS
pnpm deploy
# Or just deploy without building (if already built)
serverless deployAfter deployment, you'll get an API Gateway endpoint. Send POST requests to:
POST https://your-api-id.execute-api.us-east-1.amazonaws.com/notify
All requests must include a valid token for authentication. You can provide the token in either:
- The
x-request-tokenheader - The
tokenfield in the request body
Example with header:
curl -X POST https://your-api-id.execute-api.us-east-1.amazonaws.com/notify \
-H "Content-Type: application/json" \
-H "x-request-token: your_secure_token_here" \
-d '{
"service": "user-service",
"error": "authentication_failed",
"message": "Invalid JWT token provided",
"level": "warning",
"payload": {
"user_id": "12345",
"ip": "192.168.1.100"
}
}'Or with token in body:
curl -X POST https://your-api-id.execute-api.us-east-1.amazonaws.com/notify \
-H "Content-Type: application/json" \
-d '{
"service": "user-service",
"error": "authentication_failed",
"message": "Invalid JWT token provided",
"level": "warning",
"token": "your_secure_token_here",
"payload": {
"user_id": "12345",
"ip": "192.168.1.100"
}
}'{
"service": "payments-api",
"error": "db_connection_failed",
"message": "Database unreachable",
"level": "critical",
"timestamp": "2024-08-21T10:30:00Z",
"payload": {
"host": "db1.prod",
"attempts": 3
}
}service(string): Service name that triggered the notificationerror(string): Error identifier/slugmessage(string): Human-readable error messagelevel(string): One of"info","warning","error","critical"
timestamp(string|number|Date): Custom timestamp (defaults to current time)payload(object|null): Additional context data
curl -X POST https://your-api-id.execute-api.us-east-1.amazonaws.com/notify \
-H "Content-Type: application/json" \
-d '{
"service": "user-service",
"error": "authentication_failed",
"message": "Invalid JWT token provided",
"level": "warning",
"payload": {
"user_id": "12345",
"ip": "192.168.1.100"
}
}'Success:
{ "ok": true }Error (invalid token):
{
"ok": false,
"error": "Unauthorized: Invalid or missing request token"
}Error (validation):
{
"ok": false,
"error": "Field \"level\" is required and must be one of: info, warning, error, critical"
}Each level includes a corresponding emoji in the Telegram message:
- π‘ info: Informational messages
β οΈ warning: Warning conditions- β error: Error conditions
- π¨ critical: Critical failures
The Telegram message will be formatted as:
π¨ <b>[CRITICAL]</b> from <b>payments-api</b>
<b>Error:</b> db_connection_failed <b>Message:</b> Database unreachable
<b>Timestamp:</b> 2024-08-21T10:30:00.000Z
<b>Payload:</b>
<pre>
{
"host": "db1.prod",
"attempts": 3
}</pre
>pnpm buildpnpm build: Build the TypeScript code with esbuildpnpm deploy: Build and deploy to AWSpnpm dev: Deploy without building (for quick iterations)
The service handles various error scenarios:
- Invalid JSON: Returns 400 with error message
- Missing required fields: Returns 400 with validation error
- Invalid level: Returns 400 with allowed values
- Missing environment variables: Returns 500 with configuration error
- Telegram API failures: Returns 500 with Telegram error details
BOT_TOKEN: Your Telegram bot token from BotFatherCHAT_ID: The chat ID where notifications should be sentREQUEST_TOKEN: Secure token required for API requests
The serverless.yml file is configured for:
- Runtime: Node.js 20.x
- Region: us-east-1 (modify as needed)
- HTTP API: POST endpoint at
/notify
-
"Cannot find BOT_TOKEN or CHAT_ID"
- Ensure environment variables are set in your
.envfile - Check that serverless is reading the environment variables correctly
- Ensure environment variables are set in your
-
"Failed to send Telegram message"
- Verify your bot token is correct
- Ensure the chat ID is valid and the bot has access to send messages
- Check if the bot was removed from the chat
-
"Invalid JSON in request body"
- Ensure you're sending valid JSON
- Check Content-Type header is set to
application/json
Send a test notification:
curl -X POST https://your-endpoint.amazonaws.com/notify \
-H "Content-Type: application/json" \
-d '{
"service": "test",
"error": "setup_test",
"message": "Testing notification setup",
"level": "info"
}'ISC