Skip to main content

Webhooks

Figment's Staking API uses webhooks to send notifications about events related to the various Staking API flows. For example, when an undelegation flow is completed, a webhook can be sent to the server of your choosing.

This guide provides all the information needed to successfully manage your webhooks in the context of Figment's Staking API.

There are some additional security considerations when dealing with webhooks, covered in the HMAC and Signatures sections below.

Jump directly to the API Reference for the webhook endpoint using these links:


Host

NetworkHost
Avalancheavalanche-slate.datahub.figment.io
Cardanocardano-slate.datahub.figment.io
Cosmoscosmos-slate.datahub.figment.io
Ethereumeth-slate.datahub.figment.io
NEARnear-slate.datahub.figment.io
Polkadotpolkadot-slate.datahub.figment.io
Polygonmatic-slate.datahub.figment.io
Solanasolana-slate.datahub.figment.io

Event Types

Staking API Webhook events can be categorized by type, specific to a network code and operation. The event type format follows the pattern <network_code>.<operation>.<action>.<specifier>.

Event types are standardized, in that:

  • When a transaction is confirmed on-chain, there will be a .confirmed event ex. near.staking.delegation.confirmed

  • If a transaction fails on-chain, there will be an .error event ex. near.staking.delegation.error

  • For staking flows, whenever there is a waiting period involved the Staking API will send a delegation.activating event ex. near.staking.delegation.activating

  • When the waiting period is finished, the Staking API will send a delegation.active event ex. near.staking.delegation.active

  • Similarly, for unstaking flows the Staking API sends the delegation.deactivating event, followed by delegation.inactive

  • If there is a withdrawal action required after unstaking, the Staking API also sends a delegation.ready_for_withdrawal event

Usage

Consumers of Staking API webhooks can subscribe to events with wildcards (*), or by specifying a valid event type without a wildcard:

  • "event_types": ["*"] subscribes to all webhook events, regardless of network
  • "event_types": ["near.*"] subscribes to all webhook events for NEAR flows
  • "event_types": ["near.staking.*"] subscribes to all webhook events for NEAR staking flows
  • "event_types": ["near.staking.delegation.confirmed"] subscribes to confirmation events for NEAR staking flows
Example POST /webhook_endpoints
curl -X POST 'https://near-slate.figment.io/api/v1/webhook_endpoints' \
-H 'Authorization: API-KEY' \
-H 'Content-Type: application/json' \
-d '{
"webhook_endpoint": {
"target_url": "https://example.com/my/endpoint",
"event_types": ["near.transfer.*"],
"enabled": "true"
}
}'
Example response from /webhook_endpoints
{
"id": 16,
"event_types": ["near.transfer.*"],
"target_url": "https://example.com/my/endpoint",
"enabled": true,
"object": "webhook_endpoint",
"created": "2022-07-26T19:27:12.647Z",
"secret": "whsec_B8sidV4Bm8NnstMuP3a9TSGYov..."
}

The above example webhook ID number 16 would send a payload to the target_url for any NEAR transfer flow event, provided that enabled is set to true.

Verify the contents of webhook payloads using the HMAC signature that is sent as a response header from the Staking API. This is illustrated in the following section.

The fields which are common to all Staking API webhook payloads are flow_id and event_type. All other fields will be relevant to the action and flow.

Example Staking API Webhook Payload
{
amount: '10.0',
status: 'success',
flow_id: '49a1bab1-e3e6-4f77-8212-ee254e1ab9a3',
event_type: 'near.transfer.transfer_tx.confirmed',
transaction_hash: '2a9fnT6j5M9Fy6TFNbX2bA1Ncjh6aXK9Ky8oPBUuJwtS',
to_account_address: 'pizza.testnet',
from_account_pubkey: 'ed25519:5QA46X6NkNmsFdu9xWVBaLNowh9gGeF1c5r9u6NcxaLY',
from_account_address: 'staking-api-demo.testnet'
}

Event Type List

The event type format follows the pattern <network_code>.<operation>.<action>.<specifier>.

Staking

  • avalanche.staking.* Wildcard for all staking events

  • avalanche.staking.delegation.activating avalanche.staking.delegation.active avalanche.staking.delegation.ready_for_withdrawal

  • avalanche.staking.delegate_tx.confirmed

HMAC

HMAC (Hash-based Message Authentication Code) is a cryptographic authentication technique which uses a shared secret and a hash function such as SHA-256.

When you create a webhook endpoint with the Staking API, the response will include a secret beginning with whsec_. This is the shared secret you will use to verify future payloads sent to that webhook endpoint.

Learn more about the specifics of HMAC in the References section.

important

Code examples are provided as samples only and should not be used in production out of the box. Use at your own risk.

Here are some code examples for verifying the HMAC signatures:

const crypto = require("crypto").webcrypto;
const TOLERANCE = 300;
const WH_SECRET = "<your webhook secret>";

export default async function verifySignature(header, body) {
// get the time from the header
const timestamp = header.match(/t=([^,\s*]+)/)[1];

// get all signatures in Unit8Array format
const signatures = [...header.matchAll(/v\d+=([^,\s*]+)/g)].map((match) => {
return new Uint8Array(Math.ceil(match[1].length / 2)).map((v, i) =>
parseInt(match[1].substr(i * 2, 2), 16)
);
});

// init text encoder
const encoder = new TextEncoder();

// construct the cyptographic key
const key = await crypto.subtle.importKey(
"raw",
encoder.encode(WH_SECRET),
{ name: "HMAC", hash: "SHA-256" },
false,
["verify"]
);

// verify that at least one signature is valid
const verified = (
await Promise.all(
signatures.map(async (signature) => {
return await crypto.subtle.verify(
"HMAC",
key,
signature,
encoder.encode(`${timestamp}.${body}`)
);
})
)
).includes(true);

// check if elapsed timestamp is within tolerance
const elapsed = Math.floor(Date.now() / 1000) - Number(timestamp);
const withinTolerance = !(TOLERANCE && elapsed > TOLERANCE);

// return validity
return verified && withinTolerance;
}

Signatures

Webhooks from the Staking API are sent with the Slate-Signature header, which you can use to verify the payload. The value of that header will look like this:

t=1666214090,v1=f790a584722ff6c0ebf4e9b59835ba5b93ee824ae0a7164feba30953d6b52cee
  • t is a UNIX Epoch timestamp.
  • v1 is the signature. Each additional signature will increment the value of v v2, v3, etc.

Create New Webhook Endpoint

Create a new webhook endpoint with the specified parameters.

Route

/api/v1/webhook_endpoints

Parameters

  • webhook_endpoint* : object
    • target_url* : string The target URL to send the webhook to.
    • event_types* : string Can be a specific event type, or use an asterisk for a wildcard: ['*']
    • enabled* : boolean true / false

Response

  • id : number Id of the newly created webhook endpoint.
  • event_types : string Event type you have passed in the request parameter.
  • target_url : string The target URL to send the webhook to.
  • enabled : boolean true / false
  • object : string "webhook_endpoint"
  • created : string Timestamp when webhook endpoint was created.
  • secret : string Unique authentication string for your webhook endpoint.

Note

  • Each webhook is identified by a sequential number.
  • Currently when a webhook ID has been deleted it cannot be reused.
  • You will only be provided with the secret when you first create a webhook. Remember to capture this data!
Request
Example Response
{
"id": 13,
"event_types": [
"*"
],
"target_url": "https://example.com/my/endpoint",
"enabled": false,
"object": "webhook_endpoint",
"created": "2022-08-15T18:11:15.829Z",
"secret": "whsec_eC2MsygUnHLLDuYXCGcpHjuKzTcJsvAdQmQnx3t3gaLVcdwpv8hFA4WhjHhQz4resJZD7d4GfGx5zZr65ko7xtz5CtfY7K9dDMAq"
}


Retrieve Endpoint

Retrieve the details of a webhook endpoint.

Route

/api/v1/webhook_endpoints/[:id]

Parameters

  • For Individual Webhook Endpoint
    • Include the webhook ID number in the request URL, to retreive details for an individual webhook endpoint.
  • For All Webhook Endpoints

Response

  • object : string list
  • url : string Endpoint URL
  • has_more : boolean true / false
  • data : object
  • id : number ID of the newly created webhook endpoint.
  • event_types : string Event type you have passed in the request parameter.
  • target_url : string The target URL to send the webhook to.
  • enabled : boolean true / false
  • object : string "webhook_endpoint"
  • created : string Timestamp when webhook endpoint was created.
Request
Example Response
{
"id": 13,
"event_types": [
"*"
],
"target_url": "https://example.com/my/endpoint",
"enabled": false,
"object": "webhook_endpoint",
"created": "2022-08-15T18:11:15.829Z"
}


List Endpoints

Get the list of all your webhook endpoints.

Route

/api/v1/webhook_endpoints

Parameters

None

Response

  • object : "list".
  • url : string The endpoint URL.
  • has_more : boolean true / false
  • data : array An array of objects containing the details for each webhook:
    • id : number ID of the newly created webhook endpoint.
    • event_types : string Event type you have passed in the request parameter.
    • target_url : string The target URL to send the webhook to.
    • enabled : boolean true / false
    • object : "webhook_endpoint".
    • created : string Timestamp when the webhook endpoint was created.
Request
Example Response
{
"object": "list",
"url": "/api/v1/webhook_endpoints",
"has_more": false,
"data": [
{
"id": 14,
"event_types": [
"*"
],
"target_url": "https://example.com/my/endpoint",
"enabled": false,
"object": "webhook_endpoint",
"created": "2022-08-15T18:11:54.469Z"
},
{
"id": 13,
"event_types": [
"*"
],
"target_url": "https://example.com/my/new/endpoint",
"enabled": true,
"object": "webhook_endpoint",
"created": "2022-08-15T18:11:15.829Z"
}
]
}


Update Webhook Endpoint

Update details for an existing webhook endpoint.

Route

/api/v1/webhook_endpoints/[:id]

Parameters

  • webhook_endpoint : object
    • target_url : string The target URL to send the webhook to.
    • event_types : string Can be a specific event type, or use an asterisk as a catchall: ['*']
    • enabled : boolean true / false

Response

  • id : number ID of the newly created webhook endpoint.
  • event_types : string Event type you have passed in the request parameter.
  • target_url : string The target URL to send the webhook to.
  • enabled : boolean true / false
  • object : "webhook_endpoint"
  • created : string Timestamp when webhook endpoint was created.
Request
Example Response
{
"id": 13,
"event_types": [
"*"
],
"target_url": "https://example.com/my/new/endpoint",
"enabled": true,
"object": "webhook_endpoint",
"created": "2022-08-15T18:11:15.829Z"
}


Delete an Existing Endpoint

Delete a webhook endpoint.

Route

/api/v1/webhook_endpoints/[:id]

Parameters

Include the webhook ID number in the request URL, to delete a webhook endpoint.

Response

None.

  • The response code for a successful deletion will be 204 - No Content
Request
Example Response
""