Mono Colombia
Banking/Core

Webhooks

Receive event notifications through HTTP/HTTPS requests.

Webhooks are event notifications we send you through HTTP/HTTPS requests. The webhooks requests are composed of three important parts:

  • URL
  • Signature
  • Payload

URL

The URL is the HTTP/HTTPS address where we send you the request. You indicate the URL when you create a new webhook through our App, see the Webhook Creation section below.

Signature

Each webhook request is signed using a secret or key, the payload and the timestamp. The webhook request headers contain the signature and the timestamp in a custom header called Mono-Signature.

The header Mono-Signature is like the following example:

Mono-Signature: t=1672328528,v1=662255ca79c4b21914894d32da10189a1482cd0fee56b2765a8b472662ce55ac
  • t is the timestamp. You can use it to validate if the request is not in your desired time range, see more at replay attacks.
  • v1 is the signature version, and its value is the signature. You can use it to validate if the webhook request was sent from our system.
Currently, we only use the signature version v1.

Payload

The webhook request payload is JSON data containing the event's information. The main schema is like the following example:

{
  "event": {
    "data": {...},
    "type": "event_type_or_name"
  },
  "timestamp": "2022-12-29T15:42:08.325158Z"
}

Attempts

When a webhook request fails, the system retries this request. Each attempt is executed X seconds after the previous attempt. If the last attempt is executed and it fails, the webhook request will not be sent anymore.

AttemptTime
1immediately
230 seconds
31.5 minutes
43.5 minutes
57.5 minutes
615.5 minutes
731.5 minutes
81.06 hours
92.13 hours
104.26 hours

These times are an approximation. The system executes a maximum of ten attempts in 8.4 hours.

Webhook Events

When a webhook is created or registered the following events will be associated to it:

Accounts

  • account_credited

Bank Transfers

  • bank_transfer_approved
  • bank_transfer_rejected
  • bank_transfer_fallback_routing
  • batch_canceled
  • batch_sent
  • batch_duplicated
  • bank_transfer_change_final_state

Card Transactions

  • card_transactions

Collection Intents

  • collection_intent_credited
  • collection_intent_failed

Webhooks Creation

Webhook creation is done through the user interface. Below you will find a detailed step by step:

  1. Go to settings.
  2. Click on Personal.
  3. Click on API.
  4. Click new webhook.
  5. Insert the HTTPS/HTTP URL that you had configured to listen the events.
  6. Click on save.

If everything is working as expected, there will be an alert indicating that we successfully created your webhook, and you should be able to see the URL listed on the page.

Considerations

Webhook URLs are unique, meaning that you can only create one webhook for the same URL. If for some reason you want to create a new webhook for an existing URL in your account, you should delete the previous one and create the new one pointing to the previously deleted URL. A new secret for that URL will be generated.

Always verify that you are receiving information from the webhook in your systems.

URL Restrictions

  • It cannot be blank
  • The URL should start with http or https prefix
  • The host cannot be 127.0.0.1 or localhost
  • Must be a valid HTTP/HTTPS URL

Detail View of the Webhook

To access this view click on the arrow at the end of the column where your URL is displayed. The detailed webhook view contains the secret that is visually hidden. Click on the show/hide eyeball to see the whole secret.

Once revealed you should be able to use it to verify that we are the ones that send you the payload.

Secret sharing is discouraged. Keep your webhook secret secure.

Verifying Signatures Manually

Step 1: Extract the timestamp and signatures from the headers

Split the header using the , character as the separator, to get a list of elements:

t=1672328528
v1=662255ca79c4b21914894d32da10189a1482cd0fee56b2765a8b472662ce55ac

Step 2: Prepare the signed_payload string

The string should be as follows:

<timestamp>.<payload_rawbody>

Step 3: Check the expected signature

Compute an HMAC with the SHA256 hash function. Use the endpoint's signing secret as the key, and use the signed_payload string as the message.

An example in Ruby:

require 'openssl'

timestamp = 1672774221
raw_payload = '{"respose_body": "example"}'

signed_payload = "#{timestamp}.#{raw_payload}"

secret = "whsec_example" # grab this secret from the page

hmac = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), secret, signed_payload)

hmac
# => 652fdc1742906b4b23ce2a5f4ac417b52c264fea0207920a5e76330a87239924

The last number should be the one that you check against the one that came in the payload.

Step 4: Checking signatures

Compare the signature in the header to the expected signature. Compute the difference between the current timestamp and the received timestamp, then decide if the difference is within your time tolerance range.

To protect against timing attacks, use a constant-time string comparison to compare the expected signature to the received signatures.

Money Fields

Fields that specify money values are defined in two key value pairs, one for the currency, and other for the amount. In these fields the money is represented in the minimum unit, which is cents.

For example:

  • 240000 = 2400.00
  • 160 = 1.60

Money fields that come with decimal units represent the original value. This is the case of the fx_rates field, where "2400.32" = 2400.32.

On this page