Skip to main content

Webhook Confirmation


When a transfer charge is successful (or has failed), Sendcash Pay will make a POST request to an endpoint of your choosing (HTTPS only) with relevant information about the transfer in the request body.

Webhook Verification#

When you set your Webhook URL during the onboarding process, a Signature Token will be generated. You'll use this to verify that requests to your Webhook URL are coming from Sendcash Pay and not a malicious actor. Valid webhook requests have a header with the key X-Transfers-Signature which is an HMAC SHA256 signature of the request body (hex-encoded). The request body is signed using your Signature Token.


  1. Sign the entire request body with HMAC SHA using the Signature Token.
  2. Compare the result of this signing with the value of the X-Transfers-Signature header.
  3. If they match, then the request is indeed from Sendcash Pay.

Example with Ruby/Sinatra:

require 'sinatra'require 'openssl'
post '/webhook' do  signature_token = ENV['SIGNATURE_TOKEN']  body =  hook_signature = request.env['HTTP_X_TRANSFERS_SIGNATURE']  signature = OpenSSL::HMAC.hexdigest('sha256'), signature_token, body)
  is_valid = Rack::Utils.secure_compare(signature, hook_signature)
  if is valid    #do something with token  endend

Responding to a Webhook Request#

  • You should respond to an event with 200 OK. We consider this an acknowledgement of the webhook by your application.
  • If your application responds with any status code outside of the 2xx range, Sendcash Pay will consider it unacknowledged and thus continue to send the same webhook every few minutes.
  • You don't need to send a request body or some other parameter as it would be discarded - we only pay attention to the status code.

Webhook Request Body#

"event": "Payment.Status",    "data": {        "status": "Completed", // or "Failed"        "userId": "<your user's unique identifier>",        "paymentReference": "<your transaction's unique identifier>",        "amount": 100.23,        "description": "Transaction Successful",        "senderAccountName": "<bank account name of paying user>",        "sourceAccountNumber": "<bank account number of paying user>",        "sourceAccountType": "<bank account type of paying user>",        "sourceBankCode": "<bank code of paying user>",        "destinationAccountNumber": "<bank account number of destination account>",        "destinationBankCode": "<bank code of destination bank account>"    }}

You should use the senderAccountName provided in the response for a fraud check. This way, you can decide to not give value if the payment is coming from a bank account that doesn't match the verified name of your user.

If the senderAccountType is set to business, you can consider skipping the name validation step if your user's verified name is their individual name.

Getting transaction data (without Webhooks)#

You can use the Connect GraphQL API to get a paginated list of all transactions initiated via Sendcash Pay.