πŸͺWebhooks

Setup powerful event-driven payment workflows in minutes.

ℹ️ To see Webhooks in action, with code examples, check out our dev examples repository.

What are Webhooks?

Helio Webhooks allow developers to listen to Helio payment events and verify transactions on your application's backend.

Security: Webhooks are linked to your Helio account. Log in to the Helio dashboard to generate your API key. Each Webhook generates a `sharedSecret` used with the target API to authenticate the endpoints with a Bearer auth header. Support: Webhooks are available for Helio Pay Links on Solana, Ethereum, Polygon and BTC.

Webhook payload example


{  // the PaylinkEventPayload object
  "transaction": "...",  // JSON string of the transactionObject below
  "event": "CREATED", // PaylinkEvents enum - matches the webhook event type when creating the webhook
  "transactionObject": {
    "id": "65e1df4d0ce08148bc333b62",  // Helio transaction ID
    "paylinkId": "65dc9f9f1154beaac39976c8", // Paylink ID
    "quantity": 1,
    "createdAt": "2024-03-01T13:59:41.303Z",
    "paymentType": "PAYLINK", // or 'PAYSTREAM'
    "meta": { // the TransactionMeta object
      "id": "65e1df4d0ce08148bc333b60",
      "amount": "9900000", // amount in minimal units (lamport/Sats/Wei)
      "senderPK": "Er3RwfYqCETBTf5RktezXaNDT3zYgwBMftxBYbX8Zk1G", // customer's wallet
      "recipientPK": "Er3RwfYqCETBTf5RktezXaNDT3zYgwBMftxBYbX8Zk1G", // merchant's recipient wallet
      "customerDetails": { 
        "country": "United States",
        "deliveryAddress": "test-address",
        "email": "test@example.com",
        "fullName": "test-full-name",
        "phoneNumber": "+0123123123123",
        "discordUsername": "a11111118100",
        "discordUser": {
          "id": "1234567890", 
          "username": "test-discord-username"
        },
        "twitterUsername": "test-x-username",
        "state": "test-state",
        "street": "test-street",
        "streetNumber": "123",
        "areaCode": "90210",
        "city": "test-city"
        "additionalJSON": "\"{\\\"test\\\": 123}\"" // any additionalJSON will be JSON stringified
      },
      "productDetails": null,
      "transactionSignature": "5AYzruixQiGX8rm279cPLo7bdqaUPYMD8Z3QnBNVz2omZHaUsUKFZRmaV8W7sAHPEyExeHkjquy8mg6LHcNktg5c",
      "transactionStatus": "SUCCESS",
      "splitRevenue": false,
      "remainingAccounts": [],
      "totalAmount": "9900000",
      "affiliateAmount": "0", // Amount sent to affiliate who referred the transaction. This will normally be "0" unless referred by affiliate
      "affiliateCode": "somecode", // Affiliate code used - this will normally be undefined
      "affiliatePublicKey": "Er3RwfYqCETBTf5RktezXaNDT3zYgwBMftxBYbX8Zk1G"; // Public key (wallet address) for affiliate who referred this transaction. This will normally be undefined
      "tokenQuote": {
        "from": "SOL",
        "fromAmountDecimal": "0.01",
        "to": "SOL",
        "toAmountMinimal": "10000000"
      },
      "currency": {
        "id": "63430c8348c610068bcdc474",
        "blockchain": null
      }
    }
  }
}

The following is a curl command that will register the Webhook for paylinkID: 636a74162e72d4ad24ac9ce9 on new transaction event. This will send a POST request to targetUrl: https://target-url.com/post-endpoint.

curl -X POST \
  https://api.hel.io/v1/webhook/paylink/transaction?apiKey=YOUR_API_KEY \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer YOUR_API_SECRET' \
  -H 'cache-control: no-cache' \
  -d '
  {
     "paylinkId": "636a74162e72d4ad24ac9ce9",
     "targetUrl": "https://target-url.com/post-endpoint",
     "events": ["CREATED"]
  }
  '

Note: For Pay Link webhooks there is one event type (CREATED). This will fire when the transaction is confirmed on the blockchain and in our system. For Solana blockchain this is nearly instant.

The response of this request will look as follows:

{
    "id": "636cf9c095aeedb263968ee9",
    "paylink": "636a74162e72d4ad24ac9ce9",
    "company": "6343e77d91c393456aa56462",
    "targetUrl": "https://target-url.com/post-endpoint",
    "events": [
        "CREATED"
    ]
    "sharedToken": "PGpDZdZdxjdN+VgoxR/RHItMj0gq2BK5tEZtIisfyKe4M8l0B51qED/YqSSPwfAVtonvdXKhn+9j63b4krxGWNkO3hyPQiiu1SD2uttjEAdMeUO+3QoTNAwxuH1FzwyP"
}

The shared token is generated when you create the webhook (and cannot be updated). We will include this token when sending webhooks to your targetUrl, so you can verify that it came from Helio.

Note: if you want to delete a webhook, you will need this ID. You can also get it by listing all webhooks for a paylink.

Upon successful payment on the Pay Link 636cf9c095aeedb263968ee9 the targetUrl will receive HTTP [POST] request with the following payload:

class PaylinkEventPayload {
   event: PaylinkEvents; // e.g. 'CREATED'
   transaction: string; // JSON string value of the transactionObject
   transactionObject: Transaction;
}

class Transaction {
   id: string;
   paylinkId: string;
   quantity: number;
   fee?: string;
   createdAt: string;
   paymentType: PaymentRequestType;
   claimDetails: {
       tradingView?: {
           username: string;
       };
       discord?: {
           username: string;
       };
   };
   meta: TransactionMeta;
}

 enum TransactionStatus {
  INITIATED = 'INITIATED',
  PENDING = 'PENDING',
  SUCCESS = 'SUCCESS',
  FAILED = 'FAILED',
  CANCELED = 'CANCELED',
  SETTLED = 'SETTLED',
}

class TransactionMeta {
   id: string;
   transactionSignature: string; // transaction hash on the blockchain
   amount: string;
   recipientPK: string; // merchant's public key (wallet address)
   senderPK: string; // customer's public key (wallet address)
   customerDetails: {
       email?: string;
       discordUsername?: string;
       discordUser?: {
           id: string
           username: string
       }
       twitterUsername?: string;
       fullName?: string;
       country?: string;
       deliveryAddress?: string;
       phoneNumber?: string;
       street?: string;
       streetNumber?: string;
       city?: string;
       state?: string
       areaCode?: string;
       additionalJSON?: string;
   };
   productDetails: {  // From 'advanced options' (step 3 of paylink creation) -> additional information
       name?: string;
       value?: string;
   };
   splitRevenue: boolean;
   remainingAccounts: {
       amount: string;
       recipient: string;
   }[];
   totalAmount: string;
   affiliateAmount: string;
   affiliateCode?: string;
   affiliatePublicKey?: string;
   currency: {
       id: string;
       blockchain?: { engine: BlockchainEngine } | null;
   };
   transactionType?: TransactionType;
   tokenQuote?: TokenQuoteMeta;
   transactionStatus: TransactionStatus // e.g. 'SUCCESS'
}

// used for converting between pricing currency (from) and what they paid with (to)
// note: from could be a crypto currency (e.g. (0.1 ETH), or fiat currency (e.g. $5)
// to is always going to be a crypto currency.
// This is useful when using swaps, to see what they paid
class TokenQuoteMeta {
   from: string;
   fromAmountDecimal: string;
   to: string;
   toAmountMinimal: string;
}

class BlockchainEngine {
  id: string;
  type: BlockchainEngineType;
}

enum PaymentRequestType {
   PAYLINK = "PAYLINK",
   PAYSTREAM = "PAYSTREAM",
}

enum PaylinkEvents {
   CREATED = "CREATED",
}

enum TransactionType {
   REFUND = "REFUND",
   PAYLINK = "PAYLINK",
}

enum BlockchainEngineType {
   EVM = "EVM",
   SOL = "SOL",
   BTC = "BTC",
}

Note: When you create a Pay Link webhook (or list all webhooks for a Pay Link) you will see a sharedToken. This is sent to your endpoint when we fire a webhook, as the authorization: Bearer SHARED_TOKEN. This can be used to validate that the webhook came from Helio.

You can list all the hooks that are registered for a Pay Link with the following curl reuqest:

curl \
https://api.hel.io/v1/webhook/paylink/transaction?apiKey=YOUR_API_KEY&paylinkId=636501dad706741f1ad63770 \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer YOUR_API_SECRET' \
  -H 'cache-control: no-cache' 

This will return an array of all Webhooks that are registered for the Pay Link. In case the API key isn't associated with Pay Link, an unauthorised request will be thrown.

[
    {
        "id": "636a3838591b00789e778b79",
        "creator": undefined, // for legacy webhooks
        "paylink": "636501dad706741f1ad63779",
        "company": "6343e77d91c393456aa56422",
        "targetUrl": "https://targetUrl.com",
        "events": [
            "CREATED"
        ]
        "sharedToken": "1HSY3MM4I1hvIRp2xv83uTY3J55nIE66vuaBrutBoCCr3fChi8rY458"
    }
]

You can delete any Webhook ID by calling the delete endpoint:

curl -X DELETE \
https://api.hel.io/v1/webhook/paylink/transaction/636a75ee5a9078bb9803a681?apiKey=YOUR_API_KEY
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer YOUR_API_SECRET' \
  -H 'cache-control: no-cache' 

To be clear, in this example, 636a75ee5a9078bb9803a681 is the ID of the Webhook. You can get this when you create a webhook, or by listing all webhooks for a Pay Link

Last updated