> For the complete documentation index, see [llms.txt](https://passimpay.gitbook.io/passimpay-api/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://passimpay.gitbook.io/passimpay-api/webhook.md).

# Webhook Deposit

The notification URL is specified in the platform settings in the personal account.

Toggle 'Enable withdraw webhook' is ON in the platform settings in the personal account.

The notification is sent only after a successful incoming transaction.

**After all actions are completed, a response with a 200 status must be returned. Otherwise, there will be 2 additional attempts to resend the notification.**

**Ensure that the signature is verified for security purposes.**

<mark style="color:$danger;">To ensure the security of the integration, you must verify the sender's IP address for every incoming Webhook request.</mark>

<mark style="color:$danger;">Before processing a Webhook, you must confirm that the request originated from an authorized IP address provided by our system. Requests from unknown or unauthorized IP addresses must not be processed.</mark>

### Signature Verification Example

{% tabs %}
{% tab title="Java" %}

```java
@RestController
public class SignatureVerificationController {

    private static final String PLATFORM_ID = "your-platform-id";
    private static final String SECRET = "your-api-key";

    // Helper function to generate HMAC-SHA256 signature
    private String generateSignature(String signatureContract, String secret) throws NoSuchAlgorithmException, InvalidKeyException {
        Mac sha256HMAC = Mac.getInstance("HmacSHA256");
        SecretKeySpec secretKey = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
        sha256HMAC.init(secretKey);
        byte[] hash = sha256HMAC.doFinal(signatureContract.getBytes(StandardCharsets.UTF_8));
        StringBuilder result = new StringBuilder();
        for (byte b : hash) {
            result.append(String.format("%02x", b));
        }
        return result.toString();
    }

    // Platform notification URL
    @PostMapping("/notification")
    public ResponseEntity<String> notificationWebHook(@RequestBody Map<String, Object> body, @RequestHeader HttpHeaders headers) throws NoSuchAlgorithmException, InvalidKeyException, JsonProcessingException {
        // Signature Verification    
        ObjectMapper objectMapper = new ObjectMapper();
        String sortedBodyJson = objectMapper.writeValueAsString(body);

        // Generate the signature contract string
        String signatureContract = PLATFORM_ID + ";" + sortedBodyJson + ";" + SECRET;

        // Generate HMAC-SHA256 signature
        String signature = generateSignature(signatureContract, SECRET);

        // Get the signature from the headers
        String receivedSignature = headers.getFirst("x-signature");

        // Compare the generated signature with the received signature
        if (StringUtils.hasText(receivedSignature) && signature.equals(receivedSignature)) {
            return ResponseEntity.ok("Signature is valid");
        } else {
            return ResponseEntity.status(400).body("Invalid signature");
        }
    }
}

```

{% endtab %}

{% tab title="Python" %}

```python
body = request.get_json()

# Platform and secret keys (example placeholders)
platform_id = 'your-platform-id'
secret = 'your-api-key'

# Generate the signature contract string
signature_contract = f'{platform_id};{body};{secret}'

# Generate HMAC-SHA256 signature
signature = hmac.new(secret.encode(), signature_contract.encode(), hashlib.sha256).hexdigest()

# Get the signature from the headers
received_signature = request.headers.get('x-signature', '')

# Compare the generated signature with the received signature
if signature == received_signature:
    return 'Signature is valid', 200
else:
    return 'Invalid signature', 400
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php
// Retrieve the raw JSON body from the request
$json = file_get_contents('php://input');
$body = json_decode($json, true);

// Sort the body
$sortedBody = json_encode($body);

// Platform and secret keys (example placeholders)
$platformId = 'your-platform-id';
$secret = 'your-api-key';

// Generate the signature contract string
$signatureContract = $platformId . ";" . $sortedBody . ";" . $secret;

// Generate HMAC-SHA256 signature
$signature = hash_hmac('sha256', $signatureContract, $secret);

// Retrieve the request headers
$headers = getallheaders();

// Get the signature from the headers
$receivedSignature = $headers['x-signature'] ?? '';

// Compare the generated signature with the received signature
if ($signature === $receivedSignature) {
    echo 'Signature is valid';
    // Proceed with further processing
} else {
    echo 'Invalid signature';
    // Handle the error accordingly
}

```

{% endtab %}
{% endtabs %}

#### Headers

<table><thead><tr><th width="191">Name</th><th width="151">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>x-signature</code></td><td>string</td><td>SHA-256 encrypted signature</td></tr><tr><td><code>Content-Type</code></td><td>string</td><td>application/json</td></tr></tbody></table>

#### Request Body

<table data-full-width="false"><thead><tr><th width="226">Name</th><th width="140">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>type</code></td><td>string</td><td>The type of callback, for example, <code>deposit</code></td></tr><tr><td><code>platformId</code></td><td>integer</td><td>Your Platform ID</td></tr><tr><td><code>paymentId</code></td><td>integer</td><td>Payment ID</td></tr><tr><td><code>orderId</code></td><td>string</td><td>Order ID of your platform.</td></tr><tr><td><code>amount</code></td><td>string</td><td>Amount in cryptocurrency</td></tr><tr><td><code>txhash</code></td><td>string</td><td>The transaction hash in the blockchain system, used to track the transaction.</td></tr><tr><td><code>addressFrom</code></td><td>string</td><td>The sender’s wallet address from which the funds are being withdrawn.</td></tr><tr><td><code>addressTo</code></td><td>string</td><td>The recipient’s wallet address to which the funds are being sent.</td></tr><tr><td><code>confirmations</code></td><td>integer</td><td><p>The number of confirmations a transaction has received. This field is used in networks such as Bitcoin, Litecoin, Dogecoin, Bitcoin Cash, and Dash.</p><p>For these networks, the system sends <strong>up to two webhook notifications</strong> for the same transaction:</p><p>• the <strong>first webhook</strong> is sent when the transaction receives <strong>1 confirmation</strong>;<br>• the <strong>second webhook</strong> is sent when the transaction receives <strong>2 confirmations</strong>.</p><p>If a transaction is first detected with <strong>2 confirmations</strong>, the system sends <strong>only one webhook notification</strong> corresponding to the 2-confirmation state. In this case, the webhook for 1 confirmation is not sent.</p></td></tr><tr><td><code>destinationTag</code></td><td>integer</td><td>An additional parameter <code>tag</code>, used in Ripple  blockchain.</td></tr><tr><td><code>amountReceive</code></td><td>string</td><td>The actual credited amount to the user's balance after all deductions.</td></tr><tr><td><code>feeService</code></td><td>string</td><td>Service fee charged by the platform for processing the transaction. This fee is retained by the service provider.</td></tr><tr><td><code>feeNetwork</code></td><td>string</td><td>Blockchain network fee required for processing the transaction on-chain. This is paid to network validators/miners.</td></tr></tbody></table>

### Resending Webhook Notifications

You can resend a webhook notification from your personal account by following these steps:

1. Navigate to the transactions section in your personal account.
2. Locate and click on the desired transaction.
3. In the opened window, you will see a field displaying the webhook response.
4. Click the **"Resend"** button to resend the webhook notification.
