Understanding B2BINPAY API & “No Transfer” Callback

Have more questions? Submit a request

B2BINPAY offers a comprehensive API for crypto deposits and payouts. One important feature in its asynchronous architecture is the use of callbacks—server-to-server notifications sent to your callback_url to update you on the status of a transaction.

Among these, the “No Transfer” callback deserves special attention. Below is a practical overview of what it is, how it works, and how you should handle it securely.


1. 📡 Callback Mechanism Overview

When you create a deposit B2BINPAY, you can supply a callback_url. B2BINPAY then sends HTTP POST requests to that URL each time the transaction status changes, such as:

  • confirmed

  • failed

  • blocked

  • cancelled

  • no transfer

Most of these callbacks contain a signed JSON payload, verified using HMAC-SHA256 with your secret key. This allows you to ensure data integrity and source authenticity (No transfer callback doesn't contain Han MAC-SHA256 signature, and it will be discussed below).


2. 🛑 What is a “No Transfer” Callback?

A “No Transfer” callback is sent when:

  • A deposit expired without receiving any funds
    (→ deposit status changed from Created to Canceled).

  • A deposit was created but never received a valid transfer due to an invalid amount (either below or above the allowed range), (→ deposit status changed from Created to Unresolved).

  • A deposit reached a Paid status, but then received an additional transfer outside the allowed limits (causing a status change from Paid to Unresolved). 


3. ⚠️ No HMAC Signature on “No Transfer” Callbacks

One critical distinction:

"No Transfer" callbacks do not include an HMAC-SHA256 signature.

This is explicitly noted in B2BinPay’s documentation. Since no transaction or transfer object was created, these callbacks skip the usual signature process.

🚨 Security Implications

ConcernImplication
No cryptographic proofYou can't validate the callback using your HMAC key.
Higher spoofing riskYou must verify the source by other means (e.g., IP allowlisting).
Should not trigger irreversible actionsAvoid performing withdrawals, refunds, or state changes solely based on this type of callback.

✅ Best Practices

  • Log the event, including IP, headers, and payload.
  • Validate source IPs against B2BINPAY's documented callback IP ranges.
  • Use internal timeouts or logic to double-check whether the deposit/payout really expired or failed.
  • Avoid sensitive automation on these callbacks (like auto-rejection of payments or user bans).

4. 🔄 Example: "No Transfer" Flow in a Deposit Scenario

  1. You create a deposit with:

    {
        "data": {
            "type": "deposit",
            "id": "7383",
            "attributes": {
                "status": 2,
                "address": "TVQMvDdWBN7FiDHdJVrwqHuoHvVtT26SgP",
                "address_type": "",
                "label": null,
                "tracking_id": null,
                "confirmations_needed": null,
                "time_limit": null,
                "callback_url": "https://1b780322-7074-404b-923d-93f4ee24868a-00-1jstgloaemst2.picard.replit.dev:5000/callback",
                "inaccuracy": null,
                "target_amount_requested": null,
                "rate_requested": "1.000000000000000000",
                "rate_expired_at": null,
                "invoice_updated_at": "2025-06-10T12:12:15.441066Z",
                "payment_page": "https://pay-sandbox.b2binpay.com//en/9edc890c-7c91-4423-894d-23643eb6caf8",
                "target_paid": "0.00000000",
                "source_amount_requested": "0.000000",
                "target_paid_pending": "0.00000000",
                "assets": {
                    "USDT-TRX": {
                        "wallet_id": 628,
                        "target_paid": "20.00000000",
                        "enrolled": "13.97147700",
                        "target_paid_pending": "0.00000000",
                        "blockchain_balance": "0.00000000"
                    }
                },
                "destination": {
                    "address_type": null,
                    "address": "TVQMvDdWBN7FiDHdJVrwqHuoHvVtT26SgP"
                },
                "payment_page_redirect_url": null,
                "payment_page_button_text": null,
                "is_active": true
            },
            "relationships": {
                "currency": {
                    "data": {
                        "type": "currency",
                        "id": "2145"
                    }
                },
                "wallet": {
                    "data": {
                        "type": "wallet",
                        "id": "628"
                    }
                }
            }
        }
    }
  2. The deposit waits for incoming payment (status = 2 (created)).
  3. If the user sends crypto in time, the deposit is marked as Paid (status = 3).
  4. A no transfer callback is sent—unsigned—to your callback URL:

    {
      "data": {
        "type": "deposit",
        "id": "7383",
        "attributes": {
          "address": "TVQMvDdWBN7FiDHdJVrwqHuoHvVtT26SgP",
          "created_at": "2024-11-28T15:39:37.807456Z",
          "tracking_id": null,
          "target_paid": "20.00000000",
          "source_amount_requested": "0.000000",
          "target_amount_requested": null,
          "status": 3,
          "time_limit": null,
          "inaccuracy": null,
          "destination": {
            "address_type": null,
            "address": "TVQMvDdWBN7FiDHdJVrwqHuoHvVtT26SgP"
          }
        },
        "relationships": {
          "currency": {
            "data": {
              "type": "currency",
              "id": "2145"
            }
          },
          "wallet": {
            "data": {
              "type": "wallet",
              "id": "628"
            }
          }
        }
      },
      "included": [
        {
          "type": "currency",
          "id": "2145",
          "attributes": {
            "blockchain_name": "",
            "iso": 2145,
            "name": "TetherUS",
            "alpha": "USDT-TRX",
            "alias": "USDT",
            "tags": "",
            "exp": 6,
            "confirmation_blocks": 20,
            "minimal_transfer_amount": "1.000000",
            "block_delay": 75
          }
        }
      ]
    }

5. 🛠️ Final Recommendations

To build a secure, robust B2BINPAY integration:

  • Always verify signatures when present.
  • Handle “No Transfer” separately—log, notify users, but avoid irreversible actions based solely on it.
  • Monitor for missing callbacks in case your endpoint was down or misconfigured.

Articles in this section

Was this article helpful?
0 out of 0 found this helpful
Share

Comments

0 comments

Article is closed for comments.