Webhook

Finvix solutions are constantly evolving and, as such, are subject to continuous improvements according to our update and version control policies. Our commitment is to always offer the best possible experience for financial management, keeping our tools at the forefront of technology and complying with the highest market standards.

Finvix Webhook Notifications

Finvix APIs allow you to configure up to 5 different URLs for each type of webhook for automating financial processes, transaction notifications, and real-time updates. To configure your service and receive webhooks from Finvix, use the endpoint /companies/v1/{id}/webhooks to register your URLs.

Make sure to specify the URLs correctly for each event type in the request body, as shown in the example. The response to each webhook will be sent to the configured URLs for each event, allowing flexibility and customization according to your needs.

event_type Description
providerValidationSucceeded Provider validation was successful.
providerValidationFailed Provider validation failed.
customerValidationSucceeded Customer validation was successful.
customerValidationFailed Customer validation failed.
customerDeleteSucceeded Customer deletion was successful.
customerDeleteFailed Customer deletion failed.
transactionCompleted The transaction was successfully completed.
transactionFailed The transaction failed.
transactionCanceled The transaction was canceled.
transactionPDFCreated The transaction PDF was successfully created.
transactionXMLCreated The transaction XML was successfully created.

Webhook Security

To ensure security in sending and receiving webhooks, Finvix uses HMAC-SHA256 signatures and API keys. You must obtain the API Key and Secret before you begin receiving webhooks, as these values are used to authenticate and validate the messages.

To obtain the API Key and Secret, you need to make a POST request to the following endpoint:

POST /companies/v1/{id}/authentication/rotate?type=ApiKey
Content-Type: application/json

The response body will include the following values:

{
  "apiKey": "your-api-key",
  "apiSecret": "your-api-secret"
}

These values must be securely stored, as they will be used to generate the HMAC-SHA256 signature for each webhook you receive.

JWT Authentication (OAuth 2.0 Client Credentials)

Alternatively, you can configure the webhook to use JWT-based authentication if your integration requires OAuth 2.0 credentials. To do this, include the authentication configuration in the same POST request to /companies/v1/{id}/authentication/rotate?type=OAuth20.

Request Example


{
  "authentication": {
    "type": "jwt",
    "jwt": {
      "clientId": "fake-client-id-1234567890",
      "clientSecret": "fake-secret_AbC123!xyz-000",
      "audience": "https://api.example.com/accounting-gateway",
      "grantType": "client_credentials",
      "tokenEndpoint": "https://auth.example.com/oauth2/token",
      "headers": [
        {
          "name": "Accept-Encoding",
          "value": "gzip, deflate"
        },
        {
          "name": "Content-Type",
          "value": "application/json"
        }
      ]
    }
  }
}
	

Fields Description:

Security Headers in Webhook

When Finvix sends a webhook, the following security headers are included in the request:

The signature in the X-Finvix-Signature header must be verified in your service using the client secret and the signature payload, which is composed of JSON payload, timestap and nonce. Compare the signature generated in your system with the received signature to ensure the message has not been altered during transit.

Below, there is an example to validate the signature, using the language C# with framework .NET 8:

        
          var jsonPayload = """JSON response body here""";

          // Header x-timestamp
          var timestamp = "timestamp_value";

          // Header x-nonce
          var nonce = "nonce_value";

          // Header x-finvix-signature
          var receivedSignature = "signature_to_validate";

          // The known shared secret
          var apiSecret = "******";

          var isValid = WebhookVerifier.VerifySignature(jsonPayload, timestamp, nonce, receivedSignature, apiSecret);
          Console.WriteLine($"Webhook is valid? {isValid}");
          
          internal static class WebhookVerifier {
            internal static bool VerifySignature(string jsonPayload, string timestamp, string nonce, string receivedSignature, string apiSecret) {
                var signaturePayload = $"{jsonPayload}{timestamp}{nonce}";
                var computedSignature = GenerateSignature(apiSecret, signaturePayload);
                return computedSignature == receivedSignature;
            }

            private static string GenerateSignature(string secret, string message) {
                var encoding = new UTF8Encoding();
                var keyByte = encoding.GetBytes(secret);
                using var hmacsha256 = new HMACSHA256(keyByte);
                var messageBytes = encoding.GetBytes(message);
                var hashMessage = hmacsha256.ComputeHash(messageBytes);
                return Convert.ToBase64String(hashMessage);
            }
        }
        
      

Expected Response

  1. The service receiving the webhook must return a 200 OK status code with an empty body to confirm the correct receipt and processing of the event. If Finvix does not receive this confirmation, it will apply the retry logic described below, retrying the webhook up to a maximum of three times

  2. The service must be prepared to process the received webhook event and send the response within the established time. If your system handles additional transactions or requires post-webhook actions, ensure they are processed correctly before returning the 200 OK response to Finvix. This ensures that Finvix does not apply the retry policy unnecessarily.

  3. If the receiving service responds with any code other than 200 OK, such as 400 (Bad Request), the retry logic will not apply. This will indicate that there was an error in the request format or received data, which must be corrected in the receiving system before reprocessing the webhook.

Retry Logic

If Finvix receives any of the status codes 500, 502, 503, 504, or a network error occurs, an automatic retry policy will apply. Finvix will retry sending the webhook up to three times, with time intervals between attempts following an exponential progression, i.e., 2 seconds raised to the square of the number of retries (e.g., 2, 4, 16 seconds).

If a 400 (Bad Request) status code is received, the retry policy will not apply. This is because this code indicates an error in the request that must be corrected in the receiving service.

During retries, the system will log the failed attempts and their reasons. If the service that receives the webhook does not respond with a 200 OK code after three attempts, webhook will be marked as failed, and no further attempts will be made.

Set Up Your Webhook URL

To configure webhooks in Finvix, follow these steps:

  1. Make a POST request to the URL /api/companies/v1/{id}/webhooks, where {id} corresponds to the company ID for which you are configuring the webhook.
  2. In the request body, you must include a JSON object that specifies the URLs for each of the available events. Below are several examples of the expected format, showing how you can customize the events you want to subscribe to:

    Complete Example:

    
    {
      "url": "https://your-site.com/webhook-handler",
      "subscribedEvents": {
        "providerValidationSucceeded": true,
        "providerValidationFailed": true,
        "customerValidationSucceeded": true,
        "customerValidationFailed": true,
        "customerDeleteSucceeded": true,
        "customerDeleteFailed": true,
        "transactionCompleted": true,
        "transactionFailed": true,
        "transactionCanceled": true,
        "transactionPDFCreated": true,
        "transactionXMLCreated": true
      }
    }
        

    Example with Selected Events:

    
    {
      "url": "https://sub.your-site.com/webhook-handler",
      "subscribedEvents": {
        "providerValidationSucceeded": true,
        "providerValidationFailed": true
      }
    }
        

    Example with Disabled Events:

    
    {
      "url": "https://sub.your-site.com/webhook-handler",
      "subscribedEvents": {
        "providerValidationSucceeded": true,
        "providerValidationFailed": false
      }
    }
        

    As shown in the examples, you can customize which events you want to subscribe to by setting the values to true or false. If an event is set to false, notifications for that event will not be sent to the specified URL.

  3. Ensure that the provided URLs are accessible and prepared to receive POST requests with the configured events. Each request will include a JSON body with the event information.
  4. After configuring the URLs, you can perform tests by sending simulated events from the Finvix testing environment. Ensure your service responds with a 200 OK status code to confirm the correct receipt of the event. If this confirmation is not received, Finvix will attempt to resend the webhook according to the retry policy.

By following these steps, you will be able to configure and properly test webhooks in Finvix, ensuring that you receive real-time notifications on key events such as provider and customer validations, and completed or failed transactions.

Test the Webhook

Once you have set up the webhook URLs, test by sending simulated events from Finvix to your service to verify that your system is receiving and processing webhook notifications correctly.

If you do not receive the webhook notification, ensure that the configured URL is valid and that your service is ready to receive POST requests. Also, verify that your service responds with a 200 OK status code to confirm the event's receipt.

For webhook testing, you can use tools like Webhook.site to generate test URLs and observe how POST requests from Finvix arrive. Be sure to validate the headers and content of the request during these tests.

Error Handling and Logging

It is highly recommended that, when processing a webhook, you log each received event in detail. The logs should include the following key information:

Additionally, ensure that you capture and properly handle exceptions to prevent a temporary failure in your system from blocking future webhook processing.

Background Processing

To improve your system’s performance, it is recommended to process webhooks in the background. This means the system should return a 200 OK response immediately after receiving the webhook and then continue processing the event asynchronously. This ensures there are no delays in the response due to event processing logic.

Webhook Body Examples

Below are examples of the JSON bodies that Finvix will send to your service depending on the activated event type.

Example: providerValidationSucceeded
{
    "id": "01MORM0PT5HY7T3TPGE4XM7XPR",
    "externalUuid": "G7G&BC8WWRUF864FSTOY",
    "metaData": {
        "businessLine": "Mobility",
        "companyId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "type": "individual",
        "timeStamp": "2024-10-01T06:45:15Z",
        "status": "Active"
    },
    "partyIdentification": {
        "id": "FSEG941222FD8"
    },
    "partyName": {
        "name": "Persona de prueba"
    },
    "postalAddress": {
        "countryCode": "MX",
        "addressLine": [],
        "district": "Distrito Federal",
        "postalZone": 12345
    },
    "partyTaxSchemes": [{
        "taxScheme": {
            "id": 625
        }
    }],
    "extensions": {
      "certificates": [
        {
          "scope": "LCO",
          "number": "00001000000610419000",
          "status": "A",
          "startDate": "2021-12-15T04:31:55",
          "endDate": "2025-12-15T04:31:55"
        },
        {
          "scope": "LCO",
          "number": "00001000000818805500",
          "status": "A",
          "startDate": "2025-09-12T18:00:13",
          "endDate": "2029-09-12T18:00:53"
        }
      ]
    },
    "contact": {
        "email": "jperez@company.com"
    },
    "validationTrace": [{
        "state": "Requested",
        "description": "",
        "createdAt": "2024-10-16T06:43:15Z"
    }, {
        "state": "Validating",
        "description": "",
        "createdAt": "2024-10-16T06:44:15Z"
    }, {
        "state": "ValidatingLco",
        "description": "",
        "createdAt": "2024-10-16T06:45:15Z"
    }, {
        "state": "ValidLco",
        "description": "Cuenta con obligaciones para facturar",
        "createdAt": "2024-10-16T06:46:18Z"
    }, {
        "state": "Active",
        "description": "RFC válido, y susceptible de recibir facturas",
        "createdAt": "2024-10-16T06:47:23Z"
    }]
}
Example: providerValidationFailed
{
    "id": "01MORM0PT5HY7T3TPGE4XM7XPR",
    "externalUuid": "G7G&BC8WWRUF864FSTOY",
    "metaData": {
        "businessLine": "Mobility",
        "companyId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "type": "individual",
        "timeStamp": "2024-10-01T06:45:15Z",
        "status": "Inactive"
    },
    "partyIdentification": {
        "id": "FSEG941222FD8"
    },
    "partyName": {
        "name": "Persona de prueba"
    },
    "postalAddress": {
        "countryCode": "MX",
        "addressLine": [],
        "district": "Distrito Federal",
        "postalZone": 12345
    },
    "partyTaxSchemes": [{
        "taxScheme": {
            "id": 625
        }
    }],
    "extensions": {},
    "contact": {
        "email": "jperez@company.com"
    },
    "validationTrace": [{
        "state": "Requested",
        "description": "",
        "createdAt": "2024-10-16T06:43:15Z"
    }, {
        "state": "Validating",
        "description": "",
        "createdAt": "2024-10-16T06:44:15Z"
    }, {
        "state": "ValidatingLco",
        "description": "",
        "createdAt": "2024-10-16T06:45:15Z"
    }, {
        "state": "InvalidLco",
        "description": "No cuenta con obligaciones para facturar o no encontrado en la LCO",
        "createdAt": "2024-10-16T06:46:08Z"
    }, {
        "state": "Inactive",
        "description": "No cuenta con obligaciones para facturar o no encontrado en la LCO",
        "createdAt": "2024-10-16T06:46:45Z"
    }]
}