Skip to main content
Marqeta platform webhooks provide an optional layer of security beyond the required Basic Authentication. This optional security layer both authenticates the message and validates message integrity by employing HMAC-SHA1 or HMAC-SHA256 (keyed-hash message authentication code — Secure Hash Algorithm 1/256). In order to use this security layer, the customer-hosted endpoint must be configured to verify the message signature. This page provides information on how to implement signature verification.

Processing webhooks

The following example of Ruby code illustrates how a method on the customer-hosted endpoint should process webhook event notifications and pings. In addition to requiring access to the webhook messages, this method requires the value of the webhook’s secret field (this field is configured using the Marqeta platform’s /webhooks endpoint). The method performs these actions: First, it computes the message signature using the raw request body and the secret. It then compares the computed signature against the actual signature contained in the message. If the two signatures are equal, the signature is verified and the method proceeds to check whether the message is a ping or an event notification and processes the message accordingly. If the signatures are not equal, the message is not verified and is processed accordingly.
Ruby
def process_event_notification(http_raw_request_body, http_headers)
  digest = OpenSSL::Digest.new("sha256")
  computed_signature = OpenSSL::HMAC.hexdigest(digest, "secret", http_raw_request_body)
  marqeta_signature = http_headers.get_fields("X-Marqeta-Signature")
  if marqeta_signature == computed_signature
    # Verified request.
    request_body_hash = http_raw_request_body.to_hash
    ping_body = request_body_hash[:pings][0]
    if ping_body.token == "marqeta" && ping_body.payload = "healthcheck"
      response.status_code = 200
      response
    else
      # Insert code that checks for event notifications.
    end
  else
    # Unverified request. Insert code that responds appropriately.
  end
end
Two signature algorithms are supported: the legacy HMAC-SHA1 and the more secure HMAC-SHA256. You can configure which algorithm to use via the signature_algorithm field in the Marqeta platform’s /webhooks endpoint. If you wish to change the signature algorithm used for verification from HMAC-SHA1 to HMAC-SHA256 for enhanced security, we recommend you allow a temporary fallback. Marqeta will retry failed webhook event notifications for up to two weeks. Therefore, for up to two weeks after changing your signature algorithm, you may still receive messages with signature generated using the original algorithm. The following Ruby code illustrates how you may modify the above example to allow for either algorithm temporarily.
Ruby
def process_event_notification(http_raw_request_body, http_headers)
  marqeta_signature = http_headers.get_fields("X-Marqeta-Signature")

  # Try SHA256 first
  sha256_signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("sha256"), "secret", http_raw_request_body)
  verified = marqeta_signature == sha256_signature

  # Fallback to SHA1 if SHA256 fails
  if !verified
    sha1_signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("sha1"), "secret", http_raw_request_body)
    verified = marqeta_signature == sha1_signature
  end

  if verified
    # Verified request.
    request_body_hash = http_raw_request_body.to_hash
    ping_body = request_body_hash[:pings][0]
    if ping_body.token == "marqeta" && ping_body.payload = "healthcheck"
      response.status_code = 200
      response
    else
      # Insert code that checks for event notifications.
    end
  else
    # Unverified request. Insert code that responds appropriately.
  end
end