Skip to content

Yara Webhooks Documentation

Webhooks allow you to receive real-time notifications about events happening in your Yara account. Your application can listen for webhook events and take action when they occur.

Table of Contents


Getting Started

Prerequisites

  1. A Yara account with API access
  2. An active API key with a configured webhook URL
  3. A publicly accessible endpoint to receive webhook events

Configuring Webhooks

To receive webhooks, you need to:

  1. Generate or activate an API key in your Yara account
  2. Set the WebhookUrl in your API key configuration
  3. Store your EncryptionKey (also called Secret) securely—this is used to verify webhook signatures

Your webhook endpoint should:

  • Be publicly accessible over HTTPS
  • Accept POST requests
  • Return a 2xx status code to acknowledge receipt
  • Process requests quickly (ideally within a few seconds)

Webhook Signature Verification

Every webhook sent by Yara includes an x-yara-signature header that you should verify to ensure the request is authentic.

Algorithm

  • Hash Function: HMAC-SHA512
  • Key: Your API key's EncryptionKey (Secret)
  • Message: The raw JSON body of the webhook request

Verification Steps

  1. Extract the x-yara-signature header from the request
  2. Read the raw request body (before any JSON parsing)
  3. Compute the HMAC-SHA512 signature using:
    • Key: Your EncryptionKey (as a string)
    • Message: The raw JSON body
  4. Compare the computed signature with the header value (case-insensitive hex comparison)

Example Implementation (Go)

import (
	"crypto/hmac"
	"crypto/sha512"
	"encoding/hex"
	"fmt"
	"io"
	"net/http"
)
 
func verifyWebhookSignature(req *http.Request, secret string) (bool, error) {
	// Get the signature from headers
	providedSignature := req.Header.Get("x-yara-signature")
	if providedSignature == "" {
		return false, fmt.Errorf("missing x-yara-signature header")
	}
 
	// Read the raw body
	body, err := io.ReadAll(req.Body)
	if err != nil {
		return false, err
	}
 
	// Compute HMAC-SHA512
	h := hmac.New(sha512.New, []byte(secret))
	h.Write(body)
	expectedSignature := hex.EncodeToString(h.Sum(nil))
 
	// Compare signatures (case-insensitive)
	valid := hmac.Equal(
		[]byte(providedSignature),
		[]byte(expectedSignature),
	)
 
	return valid, nil
}

Example Implementation (Node.js)

const crypto = require('crypto');
 
function verifyWebhookSignature(req, secret) {
  const providedSignature = req.headers['x-yara-signature'];
  
  if (!providedSignature) {
    throw new Error('Missing x-yara-signature header');
  }
 
  const body = req.rawBody; // Make sure this is the raw body as a Buffer
  const hmac = crypto.createHmac('sha512', secret);
  hmac.update(body);
  const expectedSignature = hmac.digest('hex');
 
  // Case-insensitive comparison
  return providedSignature.toLowerCase() === expectedSignature.toLowerCase();
}

Example Implementation (Python)

import hmac
import hashlib
 
def verify_webhook_signature(headers, body, secret):
    """
    Verify webhook signature.
    
    Args:
        headers: Request headers dict
        body: Raw request body as bytes
        secret: Your API key's EncryptionKey
    
    Returns:
        bool: True if signature is valid
    """
    provided_signature = headers.get('x-yara-signature')
    
    if not provided_signature:
        raise ValueError('Missing x-yara-signature header')
    
    # Compute HMAC-SHA512
    expected_signature = hmac.new(
        secret.encode('utf-8'),
        body,
        hashlib.sha512
    ).hexdigest()
    
    # Case-insensitive comparison
    return hmac.compare_digest(
        provided_signature.lower(),
        expected_signature.lower()
    )

Webhook Events

Yara sends webhooks for the following events:

Event Types

Event ValueDescription
ONCHAIN_DEPOSITA cryptocurrency deposit has been confirmed on-chain
ONCHAIN_PAYOUTA cryptocurrency payout has been confirmed on-chain
TRANSFER_SUCCESSA fund transfer has completed successfully
TRANSFER_FAILEDA fund transfer has failed
WIDGET_DEPOSITA deposit via the Yara widget has been received
ONRAMP_CREATEDAn onramp has been created and a funding account has been issued
ONRAMP_FUNDING_RECEIVEDAn onramp funding payment has been received
ONRAMP_COMPLETEDAn onramp has been funded and settled successfully
ONRAMP_FAILEDAn onramp has failed during funding or settlement
SPLIT_PAYMENT_COMPLETEDA split payment virtual account has been fully funded and processed
PAYOUT_SUCCESSA payout request has completed successfully
PAYOUT_FAILEDA payout request has failed
PAYOUT_INITIATEDA payout request has been initiated and is pending

Event Payload Structure

All webhook events follow this structure:

{
  "createdAt": "2024-01-15T10:30:45.123Z",
  "event": "PAYOUT_SUCCESS",
  "data": {
    // Event-specific data (see below for each event type)
  }
}

Field Descriptions

  • createdAt (string, ISO 8601): The timestamp when the event was created
  • event (string): The type of event (see Event Types table above)
  • data (object): Event-specific payload data

Event-Specific Payloads

ONCHAIN_DEPOSIT

Fired when a cryptocurrency deposit is confirmed on-chain.

{
  "createdAt": "2024-01-15T10:30:45.123Z",
  "event": "ONCHAIN_DEPOSIT",
  "data": {
    "eventId": "evt_1234567890",
    "address": "0x742d35Cc6634C0532925a3b844Bc112e0303d9e0",
    "amount": 1.5,
    "token": "USDC",
    "chain": "ethereum",
    "txHash": "0xabc123def456...",
    "addressId": "addr_1234567890",
    "amountUsd": "1500.00"
  }
}
Fields:
  • eventId: Unique identifier for this event
  • address: Deposit destination address
  • amount: Amount received (in token units)
  • token: Token symbol (e.g., "USDC", "ETH", "BTC")
  • chain: Blockchain network (e.g., "ethereum", "polygon", "solana")
  • txHash: Transaction hash on the blockchain
  • addressId: Unique identifier for the deposit address
  • amountUsd: Equivalent amount in USD

ONCHAIN_PAYOUT

Fired when a cryptocurrency payout is confirmed on-chain.

{
  "createdAt": "2024-01-15T10:30:45.123Z",
  "event": "ONCHAIN_PAYOUT",
  "data": {
    "eventId": "evt_9876543210",
    "address": "0x742d35Cc6634C0532925a3b844Bc112e0303d9e0",
    "amount": 2.5,
    "token": "USDC",
    "chain": "ethereum",
    "txHash": "0xdef456abc789...",
    "amountUsd": "2500.00"
  }
}

Fields: Same as ONCHAIN_DEPOSIT

WIDGET_DEPOSIT

Fired when a deposit is received via the Yara widget.

{
  "createdAt": "2024-01-15T10:30:45.123Z",
  "event": "WIDGET_DEPOSIT",
  "data": {
    "eventId": "evt_5555555555",
    "amount": 3.0,
    "token": "USDT",
    "chain": "polygon",
    "address": "0x742d35Cc6634C0532925a3b844Bc112e0303d9e0",
    "txHash": "0xaaa111bbb222...",
    "amountUsd": 3000.0,
    "fiatPayoutAmount": 0.0
  }
}
Fields:
  • eventId: Unique event identifier
  • amount: Deposit amount
  • token: Token symbol
  • chain: Blockchain network
  • address: Deposit address (optional)
  • txHash: Transaction hash
  • amountUsd: USD equivalent
  • fiatPayoutAmount: Associated fiat payout amount (if applicable)

ONRAMP_CREATED

Fired when an onramp is created and Yara provisions the single-use funding account.

{
  "createdAt": "2026-07-09T03:29:59Z",
  "event": "ONRAMP_CREATED",
  "data": {
    "eventId": "460b5fc1-3b52-4aa2-a1b5-eb359bf20f7d:ONRAMP_CREATED",
    "onrampId": "460b5fc1-3b52-4aa2-a1b5-eb359bf20f7d",
    "reference": "test-mags-002",
    "status": "created",
    "fundingStatus": "ACTIVE",
    "provider": "palmpay",
    "providerReference": "24260709033042163487",
    "sourceAmount": 3000,
    "sourceCurrency": "NGN",
    "receivedAmount": 0,
    "receivedAmountUsd": 0,
    "netSourceAmount": 2950,
    "payoutAmount": 2.1135045057050292,
    "payoutCurrency": "USD",
    "recipientType": "YARA_TAG",
    "recipientName": "OLUWASEYI OLADELE",
    "recipientYaraTag": "ayo",
    "recipientAddress": "",
    "recipientBankName": "",
    "recipientAccountLast4": "",
    "fundingAccountNumber": "8776644943",
    "fundingBankName": "PalmPay",
    "fundingBankCode": "100033",
    "fundingBeneficiaryName": "OLUWASEYI OLADELE",
    "destinationSettlementTxHash": "",
    "failureReason": ""
  }
}
Fields:
  • eventId: Unique event identifier
  • onrampId: Yara onramp ID
  • reference: Caller-supplied or generated reference
  • status: Onramp lifecycle state such as created, funding_received, completed, or failed
  • fundingStatus: Funding leg status
  • provider: Funding provider, currently palmpay
  • providerReference: Provider-side order or funding reference
  • sourceAmount: Expected NGN amount
  • sourceCurrency: Source currency, currently NGN
  • receivedAmount: Actual NGN amount received
  • receivedAmountUsd: Received amount converted to USD
  • netSourceAmount: Net NGN amount after deposit-side fees
  • payoutAmount: Final payout amount
  • payoutCurrency: Destination payout currency
  • recipientType: YARA_TAG, CRYPTO_WALLET, or USD_BANK_ACCOUNT
  • recipientName: Recipient display name
  • recipientYaraTag: YaraTag when the destination is a Yara wallet
  • recipientAddress: Crypto address when the destination is a crypto wallet
  • recipientBankName: USD bank name when the destination is a USD bank account
  • recipientAccountLast4: Last 4 digits of the recipient account number for USD bank destinations
  • fundingAccountNumber: The PalmPay funding account number
  • fundingBankName: The funding bank name
  • fundingBankCode: The funding bank code
  • fundingBeneficiaryName: Funding account beneficiary name
  • destinationSettlementTxHash: Settlement transaction hash for crypto settlements when available
  • failureReason: Failure reason for failed or review-required outcomes

ONRAMP_FUNDING_RECEIVED

Fired when the expected funding payment is received for an onramp.

{
  "createdAt": "2026-07-09T03:33:29Z",
  "event": "ONRAMP_FUNDING_RECEIVED",
  "data": {
    "eventId": "460b5fc1-3b52-4aa2-a1b5-eb359bf20f7d:ONRAMP_FUNDING_RECEIVED",
    "onrampId": "460b5fc1-3b52-4aa2-a1b5-eb359bf20f7d",
    "reference": "test-mags-002",
    "status": "funding_received",
    "fundingStatus": "PAID",
    "provider": "palmpay",
    "providerReference": "24260709033042163487",
    "sourceAmount": 3000,
    "sourceCurrency": "NGN",
    "receivedAmount": 3000,
    "receivedAmountUsd": 2.1135045057050292,
    "netSourceAmount": 2950,
    "payoutAmount": 2.1135045057050292,
    "payoutCurrency": "USD",
    "recipientType": "YARA_TAG",
    "recipientName": "OLUWASEYI OLADELE",
    "recipientYaraTag": "ayo",
    "recipientAddress": "",
    "recipientBankName": "",
    "recipientAccountLast4": "",
    "fundingAccountNumber": "8776644943",
    "fundingBankName": "PalmPay",
    "fundingBankCode": "100033",
    "fundingBeneficiaryName": "OLUWASEYI OLADELE",
    "destinationSettlementTxHash": "",
    "failureReason": ""
  }
}

Fields: Same as ONRAMP_CREATED

ONRAMP_COMPLETED

Fired when an onramp has been funded and settled successfully.

{
  "createdAt": "2026-07-09T03:33:30Z",
  "event": "ONRAMP_COMPLETED",
  "data": {
    "eventId": "460b5fc1-3b52-4aa2-a1b5-eb359bf20f7d:ONRAMP_COMPLETED",
    "onrampId": "460b5fc1-3b52-4aa2-a1b5-eb359bf20f7d",
    "reference": "test-mags-002",
    "status": "completed",
    "fundingStatus": "PAID",
    "provider": "palmpay",
    "providerReference": "24260709033042163487",
    "sourceAmount": 3000,
    "sourceCurrency": "NGN",
    "receivedAmount": 3000,
    "receivedAmountUsd": 2.1135045057050292,
    "netSourceAmount": 2950,
    "payoutAmount": 2.1135045057050292,
    "payoutCurrency": "USD",
    "recipientType": "YARA_TAG",
    "recipientName": "OLUWASEYI OLADELE",
    "recipientYaraTag": "ayo",
    "recipientAddress": "",
    "recipientBankName": "",
    "recipientAccountLast4": "",
    "fundingAccountNumber": "8776644943",
    "fundingBankName": "PalmPay",
    "fundingBankCode": "100033",
    "fundingBeneficiaryName": "OLUWASEYI OLADELE",
    "destinationSettlementTxHash": "",
    "failureReason": ""
  }
}

Fields: Same as ONRAMP_CREATED

ONRAMP_FAILED

Fired when an onramp fails during funding or settlement.

{
  "createdAt": "2026-07-09T03:33:30Z",
  "event": "ONRAMP_FAILED",
  "data": {
    "eventId": "460b5fc1-3b52-4aa2-a1b5-eb359bf20f7d:ONRAMP_FAILED",
    "onrampId": "460b5fc1-3b52-4aa2-a1b5-eb359bf20f7d",
    "reference": "test-mags-002",
    "status": "failed",
    "fundingStatus": "FAILED",
    "provider": "palmpay",
    "providerReference": "24260709033042163487",
    "sourceAmount": 3000,
    "sourceCurrency": "NGN",
    "receivedAmount": 3000,
    "receivedAmountUsd": 2.1135045057050292,
    "netSourceAmount": 2950,
    "payoutAmount": 2.1135045057050292,
    "payoutCurrency": "USD",
    "recipientType": "YARA_TAG",
    "recipientName": "OLUWASEYI OLADELE",
    "recipientYaraTag": "ayo",
    "recipientAddress": "",
    "recipientBankName": "",
    "recipientAccountLast4": "",
    "fundingAccountNumber": "8776644943",
    "fundingBankName": "PalmPay",
    "fundingBankCode": "100033",
    "fundingBeneficiaryName": "OLUWASEYI OLADELE",
    "destinationSettlementTxHash": "",
    "failureReason": "destination settlement failed"
  }
}

Fields: Same as ONRAMP_CREATED

SPLIT_PAYMENT_COMPLETED

Fired when a split payment virtual account receives the exact expected amount and Yara completes processing for both the recipient payout and developer fee.

{
  "createdAt": "2026-07-09T11:10:20Z",
  "event": "SPLIT_PAYMENT_COMPLETED",
  "data": {
    "eventId": "b62e5a0a-87f0-4c54-ac63-4f88a8f6e30d:SPLIT_PAYMENT_COMPLETED",
    "splitPaymentId": "b62e5a0a-87f0-4c54-ac63-4f88a8f6e30d",
    "reference": "split-test-integration-002",
    "status": "completed",
    "baseAmount": 5000,
    "providerFee": 100,
    "developerFee": 125,
    "developerFeePercentage": 2.5,
    "totalExpectedAmount": 5225,
    "netPayoutAmount": 5000,
    "currency": "NGN",
    "recipientBankCode": "100004",
    "recipientAccountNumber": "8030959098",
    "recipientName": "OLUWASEYI TAMUNOMIEBI OLADELE"
  }
}
Fields:
  • eventId: Unique event identifier for this webhook delivery
  • splitPaymentId: Unique split payment identifier
  • reference: Client or system reference associated with the split payment
  • status: Final split payment status. For this event, the value is completed
  • baseAmount: Original recipient payout amount in the smallest NGN unit
  • providerFee: Provider fee charged for the split payment in the smallest NGN unit
  • developerFee: Developer fee credited to the API caller in the smallest NGN unit
  • developerFeePercentage: Developer fee percentage applied to the base amount
  • totalExpectedAmount: Exact amount the virtual account needed to receive before processing
  • netPayoutAmount: Amount paid out to the recipient bank account in the smallest NGN unit
  • currency: Settlement currency for the split payment
  • recipientBankCode: Destination bank code for the recipient payout
  • recipientAccountNumber: Destination bank account number for the recipient payout
  • recipientName: Resolved account name for the recipient payout

PAYOUT_SUCCESS

Fired when a payout request completes successfully.

{
  "createdAt": "2024-01-15T10:30:45.123Z",
  "event": "PAYOUT_SUCCESS",
  "data": {
    "eventId": "evt_3333333333",
    "payoutId": "payout_9876543210",
    "amount": 1.75,
    "amountUsd": 1750.0,
    "payoutCurrency": "USDC",
    "fiatAmount": 1750.0,
    "reference": "ref_payout_123456",
    "status": "completed",
    "bankCode": "GTCO",
    "bankAccountNumber": "0123456789"
  }
}
Fields:
  • eventId: Unique event identifier
  • payoutId: Unique payout identifier
  • amount: Crypto amount
  • amountUsd: USD equivalent
  • payoutCurrency: Currency sent (e.g., "USDC")
  • fiatAmount: Equivalent fiat amount
  • reference: Payout reference number
  • status: Payout status
  • bankCode: Bank code (for fiat payouts)
  • bankAccountNumber: Bank account number (for fiat payouts)

PAYOUT_FAILED

Fired when a payout request fails.

{
  "createdAt": "2024-01-15T10:30:45.123Z",
  "event": "PAYOUT_FAILED",
  "data": {
    "eventId": "evt_4444444444",
    "payoutId": "payout_1234567890",
    "amount": 0.5,
    "amountUsd": 500.0,
    "payoutCurrency": "USDC",
    "fiatAmount": 500.0,
    "reference": "ref_payout_789012",
    "status": "failed",
    "bankCode": "GTCO",
    "bankAccountNumber": "9876543210"
  }
}

Fields: Same as PAYOUT_SUCCESS

PAYOUT_INITIATED

Fired when a payout request is initiated and pending processing.

{
  "createdAt": "2024-01-15T10:30:45.123Z",
  "event": "PAYOUT_INITIATED",
  "data": {
    "eventId": "evt_2222222222",
    "payoutId": "payout_5555555555",
    "amount": 0.75,
    "amountUsd": 750.0,
    "payoutCurrency": "USDC",
    "fiatAmount": 750.0,
    "reference": "ref_payout_345678",
    "status": "pending",
    "bankCode": "GTCO",
    "bankAccountNumber": "1111111111"
  }
}

Fields: Same as PAYOUT_SUCCESS

TRANSFER_SUCCESS

Fired when a fund transfer completes successfully.

{
  "createdAt": "2024-01-15T10:30:45.123Z",
  "event": "TRANSFER_SUCCESS",
  "data": {
    // Payload structure varies based on transfer type
    // May include deposit or payout information
  }
}

TRANSFER_FAILED

Fired when a fund transfer fails.

{
  "createdAt": "2024-01-15T10:30:45.123Z",
  "event": "TRANSFER_FAILED",
  "data": {
    // Payload structure varies based on transfer type
    // May include deposit or payout information
  }
}

Retry Policy

Yara implements automatic retry logic for webhook deliveries:

Retry Mechanism

  • Initial Delivery: Webhooks are sent immediately upon event occurrence
  • Failed Delivery: If your endpoint returns a non-2xx status code or times out, Yara will retry
  • Maximum Retries: Up to 5 automatic retries
  • Backoff Strategy: Exponential backoff between retries
  • Idempotency: Each webhook event includes a unique eventId in the data payload to help you identify duplicate deliveries

Best Practices for Webhook Handling

  1. Verify Signatures: Always verify the x-yara-signature header
  2. Idempotent Processing: Use the eventId to track and deduplicate events
  3. Quick Response: Return a 2xx status code quickly; process event data asynchronously
  4. Store Events: Log all received webhooks for audit trails and debugging
  5. Handle Retries: Be prepared to receive the same event multiple times
  6. Error Handling: Return appropriate HTTP status codes:
    • 2xx: Event acknowledged and will be processed
    • 5xx: Temporary error; Yara will retry
    • Other 4xx: Permanent error; Yara will not retry

Exponential Backoff Example

If a webhook fails, retries occur with exponential backoff:

AttemptDelay (approx)
1st Retry~15 seconds
2nd Retry~30 seconds
3rd Retry~1 minute
4th Retry~2 minutes
5th Retry~4 minutes

Common Questions

How do I test webhooks locally?

Use a tunnel service like ngrok to expose a local endpoint:

ngrok http 3000

Then configure your webhook URL to point to your ngrok URL (e.g., https://abc123.ngrok.io/webhook).

Can I modify my webhook URL after creating an API key?

Yes, you can update the WebhookUrl in your API key settings at any time.

Should I trust all x-yara-signature headers?

Always verify signatures, even if the request appears to come from Yara. This protects against spoofed requests.