The notification feature allows you to be notified when an API user receives an important event.
To receive a webhook notification, you must first register your
target endpoint via PUT /notifications/configuration
Once done, your web server will be called via POST with a json payload such as this one:
{'payload_type': 'TRANSACTION', 'event_type': 'NEW_TRANSACTION_HAS_BEEN_RECEIVED', 'id': 10}
payload_type
: Enum identifying the type of the Vault object the notification is about.event_type
: Enum identifying uniquely the exact event that triggered the notification.
Can be used to run specific actions for specific events.id
: Id of the Vault object. Together with payload_type
they allow you to fetch the full
object with the corresponding endpoint.Below is a list and short description of the event types API operators can receive:
Event Type | Payload Type | Description |
---|---|---|
NEW_TRANSACTION_HAS_BEEN_SIGNED | TRANSACTION | A new transaction has been signed by the HSM |
NEW_TRANSACTION_HAS_BEEN_BROADCASTED | TRANSACTION | An new transaction has been broadcast |
NEW_TRANSACTION_HAS_FAILED | TRANSACTION | A new transaction has failed upon broadcast |
NEW_TRANSACTION_HAS_BEEN_ABORTED | TRANSACTION | A new transaction has been aborted by a User |
NEW_TRANSACTION_HAS_BEEN_RECEIVED | TRANSACTION | A new transaction has been received |
NEW_TRANSACTION_HAS_BEEN_SCORED | TRANSACTION | A new transaction has been scored by a KYT provider |
REQUEST_HAS_BEEN_CREATED | REQUEST | A new request has been created |
REQUEST_HAS_RECEIVED_AN_APPROVAL | REQUEST | A request has received an approval |
REQUEST_HAS_REACHED_STEP | REQUEST | A request has reached a new approval step |
REQUEST_HAS_REACHED_QUORUM | REQUEST | A request has reached the required quorum |
REQUEST_HAS_BEEN_ABORTED | REQUEST | A request has been aborted |
REQUEST_HAS_EXPIRED | REQUEST | A request has been pending for too long and has expired |
NEW_USER_HAS_BEEN_CREATED | USER | A new user has been created |
USER_HAS_BEEN_EDITED | USER | A user has been edited |
USER_HAS_BEEN_REVOKED | USER | A user has been revoked |
USER_HAS_BEEN_SUSPENDED | USER | A user has been suspended |
USER_HAS_BEEN_UNSUSPENDED | USER | A user has been unsuspended |
NEW_GROUP_HAS_BEEN_CREATED | GROUP | A new group has been created |
GROUP_HAS_BEEN_EDITED | GROUP | A group has been edited |
GROUP_HAS_BEEN_REVOKED | GROUP | A group has been revoked |
NEW_ACCOUNT_HAS_BEEN_CREATED | X_ACCOUNT | A new account has been created |
ACCOUNT_HAS_BEEN_EDITED | X_ACCOUNT | An account has been edited |
NEW_ENTITY_HAS_BEEN_CREATED | ENTITY | A new entity has been created |
ENTITY_HAS_BEEN_EDITED | ENTITY | An entity has been edited |
ENTITY_HAS_BEEN_REVOKED | ENTITY | An entity has been revoked |
NEW_WHITELIST_HAS_BEEN_CREATED | WHITELIST | A new whitelist has been created |
WHITELIST_HAS_BEEN_EDITED | WHITELIST | A whitelist has been edited |
Note: X_ACCOUNT
can be one of BITCOIN_ACCOUNT, ETHEREUM_ACCOUNT, ERC20_ACCOUNT, ...
By design, we've reduced the number of information in the payload to the minimum as we can't guarantee the security of the channel the same way we do with the LAM.
However, using the provided id
you can query the LAM to get more information.
You can also make sure the payload is genuine with the shared secret you've
provided during registration.
We send you the following HTTP Header X-Ledger-Signature: t=<timestamp>,v1=<signature>
timestamp
is a unix epoch timestampsignature
is a hmac sha256 signature computed with your secret and the
concatenation of the:Here is an example of signature validation and a request to the LAM using python / flask:
SECRET = "mysecret"
USER = "api_lam_user"
@app.route("/", methods=["POST"])
def webhook():
ledger_signature = request.headers["X-Ledger-Signature"]
for elem in ledger_signature.split(","):
k, v = elem.split("=")
if k == "t":
timestamp = v
elif k == "v1":
signature = v
if time.time() - int(timestamp) > 5 * 60:
raise ValueError("message is too old, possible replay attack")
to_sign = timestamp.encode() + b"." + request.data
computed_signature = hmac.new(SECRET.encode(), to_sign, "sha256").hexdigest()
if not hmac.compare_digest(signature, computed_signature):
raise ValueError("signature mismatch")
if request.json.get("payload_type") == "TRANSACTION":
tx_id = request.json["id"]
tx = requests.get(
f"http://vault-lam:5000/transactions/{tx_id}",
headers={"X-Ledger-API-User": USER, "Content-Type": "application/json"},
)
print(tx.json())
# do something with the transaction