How to configure webhook -> returning 404

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • jflores
    Member
    • Aug 2019
    • 57

    How to configure webhook -> returning 404

    Hi there -

    Disclaimer: I've never configured a webhook before and was trying it out in EspoCRM to learn. It's not going well. haha

    I've read the documentation and here's what I've done:

    1. Created a Postman API user
    2. Created a Document.create event
    3. Created a url: https://{espo_path}/api/v1/Webhook/create-document
    4. Tried to send a POST request to the above URL through Postman.
    5. I keep getting a 404 error.

    I am able to use Postman to issue GET requests via API and can see responses; so I believe my API key is working properly. Unfortunately, though, I don't have any clue about where to start looking to debug this. And I'm nowhere near convinced I'm even approaching it correctly. :-/

    Any help is appreciated!

    EspoCRM Documentation. Contribute to espocrm/documentation development by creating an account on GitHub.
  • jflores
    Member
    • Aug 2019
    • 57

    #2
    Update:

    So, it looks like I misinterpreted the way webhooks in espo work. I thought maybe Espocrm could receive events via webhook from other services.

    Espocrm can send events to another URL (which is what the instructions in the documentation are for), but I don't see anyway for Espo to receive events. Am I missing something there?

    Comment

    • yuri
      Member
      • Mar 2014
      • 8440

      #3
      There's no ability to listen to external hooks. You can create a custom API entry points with your logic there.
      Last edited by yuri; 05-05-2020, 05:12 PM.
      If you find EspoCRM good, we would greatly appreciate if you could give the project a star on GitHub. We believe our work truly deserves more recognition. Thanks.

      Comment

      • jflores
        Member
        • Aug 2019
        • 57

        #4
        For anyone who comes across this and wants to make a custom API entry point, that’s exactly what I did.

        In this case, I wanted to be able to POST data from a 3rd party form provider (Cognito Forms) into LeadCapture, but also create a Document that gets associated with that lead based on information from the POST request.

        By default, the LeadCapture payload is only equipped to handle data with fields that are mapped to the Lead Entity.

        So, what I did:

        1. Created a custom route for an API endpoint
        2. I hijacked the LeadCapture methods that already existed in order to a) allow for API Key validation and b) so I could keep the logic I had already created related to the LeadCapture
        3. Wrote a service that handled the logic in the ways I wanted to.

        This is what the implementation looks like (roughly):


        custom/Espo/Custom/Resources/routes.json
        Code:
        [
          {
            “route”: “/ExternalForm/:action/:apiKey”,
            “method”: “post”,
            “params”: {
              “controller”: “ExternalForm”,
              “action”: “:action”,
              “apiKey”: “:apiKey”
           },
            “conditions”: {
              “auth”: false
            }
          }
        ]
        This code provides a route for a POST request At the URL specified. :action and :apiKey are variable parameters that can be, well, anything. However, :action must map to some action in the controller specified.

        The auth: false condition bypasses the default authentication methods, so you don’t need an X-API-Key or HMAC key in order to be able to access the endpoint. This will prevent 401 unauthorized errors and allow you to actually use the controller method specified.

        custom/Espo/Custom/Controllers/ExternalForm.php
        Code:
        namespace Espo\Custom\Controllers;
        
        use \Espo\Core\Exceptions\Forbidden;
        use \Espo\Core\Exceptions\BadRequest;
        use \Espo\Core\Exceptions\NotFound;
        
        class ExternalForm extends \Espo\Core\Controllers\Base
        {
          public function postActionSomeExample($params, $data, $request, $response)
          {
             if (empty($params[‘apiKey’])) throw new BadRequest(‘No API Key!’);
             if (empty($data)) throw new BadRequest(‘No payload provided’);
        
             $allowOrigin = $this->getConfig()->get(‘leadCaptureAllowOrigin’, ‘*’);
             $response->headers->set(‘Access-Control-Allow-Origin’, $allowOrigin);
        
             $apiKey = $params[‘apiKey’];
             $validKey = $this->getServiceFactory()->create(‘LeadCapture’)->isApiKeyValid($apiKey);
        
             if ($validKey) {
               $lead = $this->getServiceFactory()->create(‘Lead’)->someActionName($data, $apiKey);
               return $lead
             } else {
                return ‘some error message!’;
             }
          }
        }
        This is where the variables entered in the routes.json parameters are used. First, :action maps to an action in the controller.

        So, to access this action, I would send a POST request to:

        https://{espocrm_root}/api/v1/ExternalForm/someExample/{someApiKey}

        Here “ExternalForm” matches the identifying controller specified in routes.json and someExample maps to postActionSomeExample - the action in the controller. Note the prefix postAction before the SomeExample - that tells the system what kind of request to expect. If this was a GET request, it would be getActionSomeExample, for instance.

        So, here, I first make sure we have an apiKey and data to process.

        Then, I send back response request headers, allowing the client to proceed.

        Next, I instantiate the LeadCapture service factory and use its isApiKeyValid method in order to validate the API Key, which was generated using the LeadCapture entity in the CRM.

        Then, if the key is valid, I send the data to a Lead service (someActionName action) in order to process business logic.

        That service is created in custom/Espo/Custom/Services/Lead.php, though both the name of the service, the functions available, and the business logic will all vary depending on your use case.

        In my case, my Lead Service Takes a subset of data from the ExternalForm POST request, does some stuff with it, creates a document using some of the payload data, associates it, and then using Workflow tool, I run some other tasks.

        Hopefully this helps someone else trying to figure out how to create a custom API endpoint that allows you to take advantage of another applications Webhook POST requests!

        Comment

        Working...