This project provides a set of AWS Lambda functions for sending WhatsApp messages.
Do not use for sensitive/private information.
Supported use cases:
- dispatching alertmanager alerts
- dispatching datadog alerts
- go 1.12
- node 8.10
- serverless
The service expects to find this parameter in AWS SecretsManager as a SecureString
/whatsit-serverless/<STAGE>/api-key
Where <STAGE>
is the development
/production
stage you specify.
You will also need to set up AWS Simple Email Service with a valid send address that corresponds to what is entered in env.yml for the senderEmailAddress
value.
You can use the AWS console or CLI to set up the API key and the SES.
As part of the serverless deployment, the functions will be given an IAM policy that allows them read access to these params.
make deploy-dev
make deploy-prod
serverless remove --stage XXX
Signing in to WhatsApp requires you to scan a QR code from the WhatsApp Settings screen on your phone. The process is as follows:
Send a request to the register
endpoint with the number you want to send messages from and your email address:
curl -s -XPOST -d '{"number": "15555555555", email: "[email protected]" }' https://<LAMBDA_ENDPOINT>/register?api_key=<API_KEY>
You will receive an email with a QR code. Scan it within 20 seconds to complete the sign in process.
At that point the registration command will return a numberId (SHA256 of your phone number) and a secret. You will use these in subsequent requests.
curl -s -XPOST -d '{"number": "15555555555" }' https://<LAMBDA_ENDPOINT>/verify?secret=<SECRET>
curl -s -XPOST -d '{"sender": <YOUR_NUMBER_ID>, "number": "16666666666", "message": "Hi" }' https://<LAMBDA_ENDPOINT>/alert?secret=<SECRET>
In your alertmanager.yml
add this block to your receivers:
section
receivers:
- name: 'my-serverless-whatsapp'
webhook_configs:
- url: 'https://<LAMBDA_ENDPOINT>/alert?secret=<SECRET>'
To delete a number, and its stored state (session keys, etc):
curl -s -XPOST -d '{"number": "15555555555"}' https://<LAMBDA_ENDPOINT>/delete?secret=<SECRET>
Authentication is handled via either an API key (for registration) or a per-WhatsApp-number shared secret.
The register
endpoint requires a query parameter api_key
that must equal the value stored in AWS Secrets Manager with the value of apiKeySecretsManagerKey
(configured in env.yml)
- If the API key is missing or blank on the server, the server will return a
401
. - If the API key is missing from the client's request, the server will return a
401
.
All other endpoints require a query parameter secret
which will be returned by the registration endpoint.
- If this secret is missing or blank on the server, the server will return a
401
. - If this secret is missing from the client's request, the server will return a
401
.
In all lifecycle endpoints (register, verify, delete), the Whatsapp account
number (used to send messages) is passed as the fully qualified number (e.g.,
15555555555
).
However in the endpoints that send messages, i.e., /alert
, the raw number is
not used. Instead a sender
query parameter is required. The value of
sender
is the sha256 hash of the fully qualified number. This hash is
returned as part of the response from /verify
and /register
, so if you note
that down, there is no need to calculate it yourself.
This is done in order to prevent third-party services (alertmanager, datadog, etc) from knowing what your Whatsapp number is.
JSON Payload:
number
: string containing the fully qualified number, with no spaces or punctuationemail
: an email address where you can receive a QR code
Example Request:
{
"number": "15555555555",
"email": "[email protected]"
}
Response Code:
200
: if the registration request succeeded400
: if the request payload is invalid500
: if the registration request failed
Response Body:
result
: a result messagenumberId
: the id of the number registered (the sha256 hash), to be used when sending messagessecret
: the secret to include in subsequent requests
Example Response:
{
"result": "registration complete",
"numberId": "910a625c4ba147b544e6bd2f267e130ae14c591b6ba9c25cb8573322dedbebd0",
"secret": "xxx"
}
JSON Payload:
number
: string containing the fully qualified number, with no spaces or punctuation
Example Request:
{
"number": "15555555555"
}
Response Code:
200
: if the verification succeeded400
: if the request payload is invalid500
: if the verification failed
Response Body:
result
: a result messagenumberId
: the id of the number registered (the sha256 hash), to be used when sending messages
Example Response:
{
"result": "the number '15555555555' was previously registered and can send messages",
"numberId": "910a625c4ba147b544e6bd2f267e130ae14c591b6ba9c25cb8573322dedbebd0"
}
To delete a number from the backend.
JSON Payload:
number
: string containing the fully qualified number, with no spaces or punctuation
Example Request:
{
"number": "15555555555"
}
Response Code:
200
: if the deletion succeeded400
: if the request payload is invalid500
: if the deletion failed
Response Body:
result
: a result message
Example Response:
{
"result": "the number '15555555555' is deleted"
}
An endpoint that receives alertmanager formatted json payloads containing alerts. The Whatsapp recipients are decided based on the
receiver
attribute of the payload. See
JSON Payload:
See alertmanager's <webhook_config>
Example Request:
{
"sender": "910a625c4ba147b544e6bd2f267e130ae14c591b6ba9c25cb8573322dedbebd0",
"number": "16666666666",
"message": "Testing testing 123"
}
Response Code:
200
: if the send succeeded400
: if the request payload is invalid, or if thesender
query parameter is missing404
: if thesender
query parameter is invalid (refers to non-existent number in the backend)500
: if the send failed
Response Body:
result
: a result message
Example Response:
{
"result": "ok"
}
whatsit-serverless
is licensed under the GNU Affero General Public License
(AGPL) v3+.
Copyright (C) 2019 Darren Clarke [email protected]
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along with this program. If not, see https://www.gnu.org/licenses/.