Connect Exact online with n8n via HTTP request

Hi,

I’ve tried to connect HTTP request to Exact Online. Everything seems to work fine untill the bearer token expires. Am i missing something or is there a way in the settings to refresh the token everytime the webhook receives a new call?

I receive the following message in the console; ‘www-authenticate’: 'Bearer error=“invalid_token”,error_description="The%20message%20expired%20at%2010%2F15%2F2020%2011%3A34%3A37%20AM%20and%20it%20is%20now%20…

The Exact support info says that the bearer token is valid for 10 minutes and has to be refreshed. But i don’t know how i can achieve that in the http request.

Axel

@ieceetee welcome to the community.

You probably can use the IF node. If the HTTP request failed due to token expiration then renew it and make the HTTP request with the new token else do nothing. There should be an endpoint to refresh the token.

1 Like

Thank you for your reply! I have multiple http nodes in the flow. most of the time the flow stops on the second call from start. really weird because i haven’t seen it stop on the first call. Any idea how i can tell it to refresh the token manually?

Can you share the workflow so that I can have a proper look? just select all the nodes and copy then you can paste it here.

{
  "nodes": [
    {
      "parameters": {
        "authentication": "basicAuth",
        "httpMethod": "POST",
        "path": "00e33e89-d686-4b2b-ad72-26cc77504ab6",
        "options": {
          "rawBody": true
        }
      },
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 1,
      "position": [
        120,
        60
      ],
      "webhookId": "00e33e89-d686-4b2b-ad72-26cc77504ab6",
      "credentials": {
        "httpBasicAuth": "***name***"
      }
    },
    {
      "parameters": {
        "authentication": "oAuth2",
        "url": "=https://start.exactonline.nl/api/v1/2794323/crm/Accounts?$select=ID,Name,Code,Email&$filter=IsSales eq true and trim(Email) eq '{{$node[\"Webhook\"].json[\"body\"][\"klant-email\"]}}'",
        "allowUnauthorizedCerts": true,
        "options": {
          "fullResponse": false,
          "timeout": 10000
        },
        "headerParametersUi": {
          "parameter": []
        },
        "queryParametersUi": {
          "parameter": []
        }
      },
      "name": "Exact gebruiker opvragen",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        310,
        60
      ],
      "notesInFlow": true,
      "credentials": {
        "oAuth2Api": "Exact test"
      },
      "color": "#DD0000",
      "notes": "Exactonline gebruikers opzoeken op basis van emailadres"
    },
    {
      "parameters": {
        "authentication": "oAuth2",
        "requestMethod": "POST",
        "url": "=https://start.exactonline.nl/api/v1/2794323/salesorder/SalesOrders",
        "jsonParameters": true,
        "options": {
          "bodyContentCustomMimeType": "application/json",
          "followRedirect": true
        },
        "bodyParametersJson": "={\n\n\t\"Description\": \"{{$node[\"Webhook\"].json[\"body\"][\"onderdelen\"]}}\",\n\n\t\"OrderedBy\": \"{{$node[\"Exact gebruiker opvragen\"].json[\"d\"][\"results\"][0][\"ID\"]}}\",\t\n\t\"DeliverTo\" : \"{{$node[\"Exact afleveradres opvragen\"].json[\"d\"][\"results\"][0][\"ID\"]}}\",\n\t\"DeliveryDate\" : \"{{$node[\"Webhook\"].json[\"body\"][\"ophaal-datum\"]}}\",\n\t\"Remarks\" : \"{{$node[\"Webhook\"].json[\"body\"][\"afleveropmerkingen\"]}}\",\n\t\"SalesOrderLines\":\n\n\t\t[\n\n\t\t\t{\n\t\t\t\t\"Description\": \"Afhaalservice\",\n\t\t\t\t\"Item\": \"7d67222d-4efc-4f5d-bd00-bdcab9cb0096\",\n\t\t\t\t\"Quantity\": \"1\",\n\t\t\t\t\"DeliveryDate\": \"{{$node[\"Webhook\"].json[\"body\"][\"ophaal-datum\"]}}\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Description\": \"{{$node[\"Webhook\"].json[\"body\"][\"aflever-bedrijfsnaam\"]}}, {{$node[\"Webhook\"].json[\"body\"][\"aflever-postcode\"]}}, {{$node[\"Webhook\"].json[\"body\"][\"aflever-straat\"]}}, {{$node[\"Webhook\"].json[\"body\"][\"aflever-plaats\"]}}, {{$node[\"Webhook\"].json[\"body\"][\"aflever-land\"]}}\",\n\t\t\t\t\"Item\": \"82158cbe-60bc-457d-82af-196f66155c0f\",\n\t\t\t\t\"Quantity\": \"1\",\n\t\t\t\t\"UnitPrice\": \"{{$node[\"Webhook\"].json[\"body\"][\"prijs\"]}}\",\n\t\t\t\t\"DeliveryDate\": \"{{$node[\"Webhook\"].json[\"body\"][\"afleverdatum\"]}}\"\n\t\t\t}\n\n\n\t\t]\n\n}"
      },
      "name": "Exact salesorder aanmaken",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        1220,
        -130
      ],
      "notesInFlow": false,
      "credentials": {
        "oAuth2Api": "Exact test"
      },
      "color": "#DD0000"
    },
    {
      "parameters": {
        "authentication": "oAuth2",
        "requestMethod": "POST",
        "url": "=https://start.exactonline.nl/api/v1/2794323/crm/Accounts",
        "jsonParameters": true,
        "options": {
          "bodyContentCustomMimeType": "application/json",
          "followRedirect": true,
          "timeout": 10000
        },
        "bodyParametersJson": "={ \n  \"AddressLine1\" : \"{{$node[\"Webhook\"].json[\"body\"][\"klant-straat\"]}}\",\n  \"City\" : \"{{$node[\"Webhook\"].json[\"body\"][\"klant-plaats\"]}}\",\n  \"Country\" : \"{{$node[\"Webhook\"].json[\"body\"][\"klant-land\"]}}\",\n  \"Email\" : \"{{$node[\"Webhook\"].json[\"body\"][\"klant-email\"]}}\",\n  \"Name\" : \"{{$node[\"Webhook\"].json[\"body\"][\"klant-bedrijfsnaam\"]}}\",\n  \"Postcode\" : \"{{$node[\"Webhook\"].json[\"body\"][\"klant-postcode\"]}}\",\n  \"Status\" : \"C\"\n}"
      },
      "name": "Exact gebruiker aanmaken",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        660,
        300
      ],
      "notesInFlow": false,
      "credentials": {
        "oAuth2Api": "Exact test"
      },
      "color": "#DD0000"
    },
    {
      "parameters": {
        "authentication": "oAuth2",
        "requestMethod": "POST",
        "url": "=https://start.exactonline.nl/api/v1/2794323/crm/Accounts",
        "allowUnauthorizedCerts": true,
        "jsonParameters": true,
        "options": {
          "bodyContentCustomMimeType": "application/json",
          "followRedirect": true
        },
        "bodyParametersJson": "={\n\"AddressLine1\" : \"{{$node[\"Webhook\"].json[\"body\"][\"aflever-straat\"]}}\",\n\"City\" : \"{{$node[\"Webhook\"].json[\"body\"][\"aflever-plaats\"]}}\",\n\"Country\" : \"{{$node[\"Webhook\"].json[\"body\"][\"aflever-land\"]}}\",\n\"Email\" : \"{{$node[\"Webhook\"].json[\"body\"][\"aflever-email\"]}}\",\n\"Name\" : \"{{$node[\"Webhook\"].json[\"body\"][\"aflever-bedrijfsnaam\"]}}\",\n\"Postcode\" : \"{{$node[\"Webhook\"].json[\"body\"][\"aflever-postcode\"]}}\",\n\"Status\" : \"S\"\n}"
      },
      "name": "Exact verzenden naar aanmaken",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        1160,
        300
      ],
      "notesInFlow": false,
      "retryOnFail": true,
      "waitBetweenTries": 2000,
      "credentials": {
        "oAuth2Api": "Exact test"
      },
      "color": "#DD0000"
    },
    {
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{$node[\"Exact gebruiker opvragen\"].json[\"d\"][\"results\"].length}}",
              "operation": "contains",
              "value2": "1"
            }
          ]
        },
        "combineOperation": "any"
      },
      "name": "Bestaat klant in exact",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        510,
        60
      ],
      "alwaysOutputData": false,
      "notesInFlow": false
    },
    {
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{$node[\"Exact afleveradres opvragen\"].json[\"d\"][\"results\"].length}}",
              "operation": "contains",
              "value2": "1"
            }
          ]
        },
        "combineOperation": "any"
      },
      "name": "bestaat klant verzendadres in exact",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        980,
        -110
      ]
    },
    {
      "parameters": {
        "authentication": "oAuth2",
        "url": "=https://start.exactonline.nl/api/v1/2794323/crm/Accounts?$select=ID,Name,Code,Email,AddressLine1&$filter=trim(Email)+eq+'{{$node[\"Webhook\"].json[\"body\"][\"aflever-email\"]}}'+and+AddressLine1+eq+'{{$node[\"Webhook\"].json[\"body\"][\"aflever-straat\"]}}'",
        "options": {
          "fullResponse": false,
          "followRedirect": true,
          "ignoreResponseCode": false,
          "timeout": 2000
        },
        "headerParametersUi": {
          "parameter": []
        },
        "queryParametersUi": {
          "parameter": []
        }
      },
      "name": "Exact afleveradres opvragen",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        790,
        40
      ],
      "notesInFlow": true,
      "retryOnFail": true,
      "waitBetweenTries": 1000,
      "maxTries": 2,
      "executeOnce": false,
      "alwaysOutputData": true,
      "credentials": {
        "oAuth2Api": "Exact test"
      },
      "color": "#DD0000",
      "notes": "Exactonline gebruikers opzoeken op basis van emailadres"
    },
    {
      "parameters": {
        "fromEmail": "***@***",
        "toEmail": "***@***",
        "text": "=Success er is een nieuwe salesorder aangemaakt",
        "options": {}
      },
      "name": "Send Email",
      "type": "n8n-nodes-base.emailSend",
      "typeVersion": 1,
      "position": [
        1430,
        -130
      ],
      "credentials": {
        "smtp": "***"
      }
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Exact gebruiker opvragen",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Exact gebruiker opvragen": {
      "main": [
        [
          {
            "node": "Bestaat klant in exact",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Exact salesorder aanmaken": {
      "main": [
        [
          {
            "node": "Send Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Exact gebruiker aanmaken": {
      "main": [
        [
          {
            "node": "Exact gebruiker opvragen",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Exact verzenden naar aanmaken": {
      "main": [
        [
          {
            "node": "Exact afleveradres opvragen",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Bestaat klant in exact": {
      "main": [
        [
          {
            "node": "Exact afleveradres opvragen",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Exact gebruiker aanmaken",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "bestaat klant verzendadres in exact": {
      "main": [
        [
          {
            "node": "Exact salesorder aanmaken",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Exact verzenden naar aanmaken",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Exact afleveradres opvragen": {
      "main": [
        [
          {
            "node": "bestaat klant verzendadres in exact",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

I tried to solve the problem with the if node as requested with no result unfortunately.

ahhh sorry, completely missed the message where you shared the workflow. Will check it out today and provide feedback. @ieceetee

Ok, I think I found the issue. The HTTP Node using the OAuth2 authentication method automatically refreshes the token for you. However, by default, the client id and secret are not sent in the body when calling the endpoint to refresh the token, and according to the docs, this is needed. I added an option called Include Credentials on Body (set it to true) to the OAuth2 credentials, and it should do the work. I created a branch that you can use to test locally. Please, let me know if that fixes the issue.

Thank you very much for the effort! How can i apply this in my linux installed n8n?

Here is the development guide:

The only thing you have to change is that for the step " Actual n8n setup -> 1" you run the following line instead:

git clone https://github.com/RicardoE105/n8n.git

Hi I get the following error on running the flow and pushing the webhook request:

ERROR: Promise.allSettled is not a function

TypeError: Promise.allSettled is not a function
    at Object.execute (/home/ieceetee/n8n/packages/nodes-base/nodes/HttpRequest.node.ts:835:43)
    at Workflow.runNode (/home/ieceetee/n8n/packages/workflow/src/Workflow.ts:975:28)
    at returnPromise (/home/ieceetee/n8n/packages/core/src/WorkflowExecute.ts:596:41)

Please update your Node.js version to 12.9 or later.

unfortunatily after the update i received the following message on start:

(node:21670) UnhandledPromiseRejectionWarning: DriverPackageNotInstalledError: SQLite package has not been found installed. Try to install it: npm install sqlite3 --save
at new DriverPackageNotInstalledError (/home/ieceetee/n8n/src/error/DriverPackageNotInstalledError.ts:8:9)
at SqliteDriver.loadDependencies (/home/ieceetee/n8n/src/driver/sqlite/SqliteDriver.ts:135:19)
at new SqliteDriver (/home/ieceetee/n8n/src/driver/sqlite/SqliteDriver.ts:49:14)
at DriverFactory.create (/home/ieceetee/n8n/src/driver/DriverFactory.ts:43:24)
at new Connection (/home/ieceetee/n8n/src/connection/Connection.ts:128:43)
at ConnectionManager.create (/home/ieceetee/n8n/src/connection/ConnectionManager.ts:64:28)
at Object. (/home/ieceetee/n8n/src/index.ts:228:35)
at step (/home/ieceetee/n8n/node_modules/typeorm/node_modules/tslib/tslib.js:141:27)
at Object.next (/home/ieceetee/n8n/node_modules/typeorm/node_modules/tslib/tslib.js:122:57)
at /home/ieceetee/n8n/node_modules/typeorm/node_modules/tslib/tslib.js:115:75
(node:21670) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=strict (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
(node:21670) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
UserSettings got generated and saved to: /root/.n8n/config
(node:21670) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 2)
(node:21670) UnhandledPromiseRejectionWarning: Error: There was an error: SQLite package has not been found installed. Try to install it: npm install sqlite3 --save
at Object.error (/home/ieceetee/n8n/node_modules/@oclif/errors/lib/index.js:26:15)
at Start.error (/home/ieceetee/n8n/node_modules/@oclif/command/lib/command.js:60:23)
at /home/ieceetee/n8n/packages/cli/commands/start.ts:231:10
(node:21670) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=strict (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 3)

Best to simply start over again from the beginning. Something must have gone wrong. sqlite3 is a dependency of n8n so it should definitely be there.

I tried to start over again on Linux and Windows. Both with no luck with the modified master.

Below the error on windows after the run build:

../../node_modules/jest-diff/build/diffLines.d.ts:8:13 - error TS1005: '=' expected.

8 import type { DiffOptions } from './types';
              ~

../../node_modules/jest-diff/build/diffLines.d.ts:8:34 - error TS1005: ';' expected.

8 import type { DiffOptions } from './types';
                                   ~~~~~~~~~

../../node_modules/jest-diff/build/index.d.ts:10:13 - error TS1005: '=' expected.

10 import type { DiffOptions } from './types';
               ~

../../node_modules/jest-diff/build/index.d.ts:10:34 - error TS1005: ';' expected.

10 import type { DiffOptions } from './types';
                                    ~~~~~~~~~

../../node_modules/jest-diff/build/index.d.ts:11:1 - error TS1128: Declaration or statement expected.

11 export type { DiffOptions, DiffOptionsColor } from './types';
   ~~~~~~

../../node_modules/jest-diff/build/index.d.ts:11:13 - error TS1005: ';' expected.

11 export type { DiffOptions, DiffOptionsColor } from './types';
               ~

../../node_modules/jest-diff/build/index.d.ts:11:52 - error TS1005: ';' expected.

11 export type { DiffOptions, DiffOptionsColor } from './types';
                                                      ~~~~~~~~~

../../node_modules/jest-diff/build/printDiffs.d.ts:8:13 - error TS1005: '=' expected.

8 import type { DiffOptions, DiffOptionsNormalized } from './types';
              ~

../../node_modules/jest-diff/build/printDiffs.d.ts:8:57 - error TS1005: ';' expected.

8 import type { DiffOptions, DiffOptionsNormalized } from './types';
                                                          ~~~~~~~~~

../../node_modules/pretty-format/build/index.d.ts:7:13 - error TS1005: '=' expected.

7 import type * as PrettyFormat from './types';
              ~

../../node_modules/pretty-format/build/index.d.ts:7:18 - error TS1005: ';' expected.

7 import type * as PrettyFormat from './types';
                   ~~~~~~~~~~~~

../../node_modules/pretty-format/build/index.d.ts:7:31 - error TS1005: ';' expected.

7 import type * as PrettyFormat from './types';
                                ~~~~

../../node_modules/pretty-format/build/index.d.ts:7:36 - error TS1005: ';' expected.

7 import type * as PrettyFormat from './types';
                                     ~~~~~~~~~


Found 13 errors.

npm ERR! code ELIFECYCLE
npm ERR! errno 2
npm ERR! [email protected] build: `tsc`
npm ERR! Exit status 2
npm ERR!
npm ERR! Failed at the [email protected] build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\UNAME\AppData\Roaming\npm-cache\_logs\2020-10-27T07_39_28_139Z-debug.log
lerna ERR! npm run build exited 2 in 'n8n-workflow'
lerna ERR! npm run build exited 2 in 'n8n-workflow'
npm ERR! code ELIFECYCLE
npm ERR! errno 2
npm ERR! [email protected] build: `lerna exec npm run build`
npm ERR! Exit status 2
npm ERR!
npm ERR! Failed at the [email protected] build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\UNAME\AppData\Roaming\npm-cache\_logs\2020-10-27T07_39_28_186Z-debug.log

Hey @ieceetee,

I ran into a similar issue and updating n8n fixed it for me. Let us know if you still have the same issue.

The latest git clone works just fine, its only the modified version of @RicardoE105 i cannot get working for some reason.

Then probably a dependency changed and it got fixed in the meantime. What you can do is to merge master in the branch from @RicardoE105. Then you will get the latest changes and it should work fine.

Just had the same issue with a stalled branch.

Steps I took to fix:

  • Remove node_modules folder from project root folder
  • Remove recursively all other node_module files
  • Do the same for all package-lock.json files (root and inside packages folder)
  • In my case for development: run lerna bootstrap --hoist to download dependencies and go hacking
  • Success!
1 Like

First of all thank you for the support from everyone, i’m really gratefull.

I have the instance running with the modified http request node. but in the node i get the following error and cannot choose the credentials;

Credential type not known

Credentials of type “httpOAuth2Api” are not known.