Format & Signature
Webhooks are HTTP notifications sent from Lago to your application.
The messages are sent as a POST
to the URL defined in the settings of your Lago workspace.
Message format
POST __WEBHOOK_URL__
{
"webhook_type": "__TYPE__",
"object_type": "OBJECT_TYPE",
"__OBJECT__": {}
}
Signature
Allong with the payload the message contains a X-Lago-Signature
HTTP header.
It is used to ensure the message is Coming from Lago and that the message has not been altered.
To verify the signature, you must decode the signature and compare the result with the body of the webhook.
1. Retrieve the public key
- Python
- Node.js
- Ruby
from lago_python_client import Client
client = Client(api_key='__YOUR_API_KEY__')
webhooks_public_key = client.webhooks().public_key()
import Client from 'lago-nodejs-client'
let client = new Client('__YOUR_API_KEY__')
let webhooksPublicKey = client.webhookPublicKey()
require 'net/http'
api_key = "__YOUR_API_KEY__"
uri = URI('https://api.getlago.com/api/v1/webhooks/public_key')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
response = http.send_request(
'GET',
uri.request_uri,
'',
{ 'Authorization' => "Bearer #{api_key}" }
)
webhooks_public_key = response.body
tip
You should persist the public key on you side to prevent querying it for each webhook
2. Decode and validate the signature
- Python
- Node.js
- Ruby
import jwt
decoded_signature = jwt.decode(
request.headers.get('X-Lago-Signature'),
webhooks_public_key,
algorithms=['RS256'],
issuer="https://api.getlago.com"
)
decoded_signature['data'] == request.body
import jwt from 'jsonwebtoken';
let token = request.header('X-Lago-Signature')
jwt.verify(token, webhooksPublicKey, {
algorithms: ['RS256'],
issuer: 'https://api.getlago.com' },
function (err, payload) {
payload === request.body
});
require 'openssl'
require 'jwt'
decoded_signature = JWT.decode(
request.headers['X-Lago-Signature'],
OpenSSL::PKey::RSA.new(Base64.decode64(webhooks_public_key)),
true,
{
algorithm: 'RS256',
iss: "https://api.getlago.com",
verify_iss: true,
},
).first
decoded_signature['data'] == request.body