AutomationFlowsData & Sheets › Better Oauth2.0 Workflow for Pipedrive CRM with Supabase

Better Oauth2.0 Workflow for Pipedrive CRM with Supabase

ByPriya Jain @processease on n8n.io

This workflow provides an OAuth 2.0 auth token refresh process for better control. Developers can utilize it as an alternative to n8n's built-in OAuth flow to achieve improved control and visibility. In this template, I've used Pipedrive API, but users can apply it with any app…

Webhook trigger★★★★☆ complexity29 nodesStop And ErrorSupabaseHTTP Request
Data & Sheets Trigger: Webhook Nodes: 29 Complexity: ★★★★☆ Added:
Better Oauth2.0 Workflow for Pipedrive CRM with Supabase — n8n workflow card showing Stop And Error, Supabase, HTTP Request integration

This workflow corresponds to n8n.io template #2319 — we link there as the canonical source.

This workflow follows the HTTP Request → Stopanderror recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "id": "IYgbtNpyB4E6Jbxo",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "2. Refresh Pipedrive tokens",
  "tags": [],
  "nodes": [
    {
      "id": "2b66edcd-c71a-4dac-971f-deb1b09ef85b",
      "name": "Stop and Error",
      "type": "n8n-nodes-base.stopAndError",
      "position": [
        1460,
        -80
      ],
      "parameters": {
        "errorMessage": "Token refresh failed"
      },
      "typeVersion": 1,
      "alwaysOutputData": false
    },
    {
      "id": "b48d6760-766e-4b39-be35-89de7dc3ab5e",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        60,
        -300
      ],
      "parameters": {
        "color": 5,
        "width": 872,
        "height": 97,
        "content": "## Step 2:\nCreate a workflow to refresh your access token when the access token requires a refresh."
      },
      "typeVersion": 1
    },
    {
      "id": "6119eef3-9ffa-45a1-b238-412738e7529e",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        280,
        -80
      ],
      "parameters": {
        "height": 211,
        "content": "\n\n\n\n\n\n\n\nPost unique data to identify your row in Database and be able to fetch the existing access and refresh token"
      },
      "typeVersion": 1
    },
    {
      "id": "2d76be21-95e1-4747-b761-126b133e8264",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        980,
        -220
      ],
      "parameters": {
        "content": "## Get token from pipedrive"
      },
      "typeVersion": 1
    },
    {
      "id": "9a44eb63-9d31-4b24-9171-1f9a828a5c52",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        100,
        -740
      ],
      "parameters": {
        "color": 5,
        "width": 995,
        "height": 82,
        "content": "## Step 1:\nSave Refresh token and Access token to DB when authenticated by user and installed.  "
      },
      "typeVersion": 1
    },
    {
      "id": "f3247e6a-7c1c-4479-9f83-f3bc4146f254",
      "name": "Insert",
      "type": "n8n-nodes-base.supabase",
      "position": [
        1600,
        -660
      ],
      "parameters": {
        "tableId": "App_tok",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "ref_token",
              "fieldValue": "={{ $node[\"Generate Refresh Token from authcode\"].json[\"body\"][\"refresh_token\"] }}"
            },
            {
              "fieldId": "acc_token",
              "fieldValue": "={{ $node[\"Generate Refresh Token from authcode\"].json[\"body\"][\"access_token\"] }}"
            },
            {
              "fieldId": "Platform",
              "fieldValue": "Pipedrive"
            },
            {
              "fieldId": "created_at",
              "fieldValue": "={{$now.toUTC().toString()}}"
            },
            {
              "fieldId": "updated_at",
              "fieldValue": "={{$now.toUTC().toString()}}"
            }
          ]
        }
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "f7ad45d0-7055-45f4-9971-031ffebfdbda",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        500,
        -640
      ],
      "parameters": {
        "content": "You can also use SET NODE + tobase64 function as done in step 2"
      },
      "typeVersion": 1
    },
    {
      "id": "e14e2dac-e84b-475f-a01b-14bb723eedc8",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        100,
        200
      ],
      "parameters": {
        "color": 5,
        "width": 1644,
        "height": 80,
        "content": "## Step 3:\nMake an actual API call. In this example, we are using search person API. Please refer to Pipedrive API documentation for your specific use case. "
      },
      "typeVersion": 1
    },
    {
      "id": "b450c928-e0e4-4f49-829e-03b61828d4d9",
      "name": "Get Pipedrive Token",
      "type": "n8n-nodes-base.supabase",
      "position": [
        600,
        660
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "Platform",
              "keyValue": "Pipedrive"
            },
            {
              "keyName": "AppId",
              "keyValue": "57db0bab2932f657"
            }
          ]
        },
        "tableId": "App_tok",
        "operation": "get"
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "f92a957a-d0ef-4037-8657-74e7fe74fe6d",
      "name": "Get contact from Pipedrive",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        900,
        660
      ],
      "parameters": {
        "url": "=https://priyajain-sandbox.pipedrive.com/api/v2/persons/search?fields=email&term={{ $node[\"Receive request\"].json[\"body\"][\"person\"][\"email\"] }}",
        "options": {
          "response": {
            "response": {
              "fullResponse": true
            }
          }
        },
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Accept",
              "value": "application/json"
            },
            {
              "name": "Authorization",
              "value": "=Bearer {{ $node[\"Get Pipedrive Token\"].json[\"acc_token\"] }}"
            }
          ]
        }
      },
      "typeVersion": 4,
      "continueOnFail": true,
      "alwaysOutputData": false
    },
    {
      "id": "bff21156-3da0-4cf3-b3de-c24d8abe7577",
      "name": "Access Token Invalid",
      "type": "n8n-nodes-base.if",
      "position": [
        1160,
        700
      ],
      "parameters": {
        "conditions": {
          "boolean": [
            {
              "value1": "={{ $json[\"error\"][\"message\"].includes(\"Invalid token: access token is invalid\") }}",
              "value2": "={{ true }}"
            }
          ]
        },
        "combineOperation": "any"
      },
      "typeVersion": 1
    },
    {
      "id": "9fd832b1-2af9-48c2-9d57-86a9f34bdd78",
      "name": "Success",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1440,
        720
      ],
      "parameters": {
        "options": {
          "responseCode": 200
        },
        "respondWith": "json",
        "responseBody": "={{ $node[\"Get contact from Pipedrive\"].json[\"body\"][\"data\"][\"items\"][\"0\"][\"item\"][\"name\"] }}"
      },
      "typeVersion": 1
    },
    {
      "id": "daf33b32-ff7b-4d7e-8fd0-d54dfaddf405",
      "name": "Refresh Access Token",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1360,
        320
      ],
      "parameters": {
        "url": "http://localhost:5678/webhook/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
        "method": "POST",
        "options": {},
        "jsonBody": "{\n\n  \"appId\":\"57db0bab2932f657\"\n\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBasicAuth"
      },
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "6759a890-6c2a-4bb1-aae9-9b8723b9e143",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        580,
        420
      ],
      "parameters": {
        "width": 668,
        "content": "## Loop back to fecth the  refreshed Access Token\n### Note:\nYou can add further conditions and use Switch  statemen tinstead of IF to validate API response based on your use case."
      },
      "typeVersion": 1
    },
    {
      "id": "d975ce9f-2ef2-46b1-9d30-4f6e06e19b7e",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        120,
        -960
      ],
      "parameters": {
        "width": 1413,
        "content": "## 1. This workflow helps you create your own Oauth 2.0 token refresh system. It helps you have better control of your oauth 2.0 auth process.\n## 2. I am using Pipedrive API here. However, you can re-use this for other similar applications. "
      },
      "typeVersion": 1
    },
    {
      "id": "40d59a94-563d-459c-91d0-4206c2a19704",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        180,
        580
      ],
      "parameters": {
        "height": 248,
        "content": "A 3rd partyapplication posting the request to the webhook"
      },
      "typeVersion": 1
    },
    {
      "id": "03945766-570c-47db-82c6-2c973e45106d",
      "name": "convert clientId and secret to base64",
      "type": "n8n-nodes-base.code",
      "position": [
        560,
        -560
      ],
      "parameters": {
        "jsCode": "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\nconst client_id = \"57db0bab2932f657\";\nconst client_secret = \"YOUR_AWS_SECRET_KEY_HERE\";\n\n// Combine client_id and client_secret with a colon\nconst combinedString = client_id+\":\"+client_secret;\n\n// Encode the combined string in Base64\nconst encodedString = Buffer.from(combinedString).toString('base64');\n\n// Create the Authorization header value\nconst authorizationHeader = `Basic ${encodedString}`;\n\nreturn {\"authheader\":authorizationHeader};"
      },
      "typeVersion": 2
    },
    {
      "id": "8ca6eb93-6994-4536-b61e-d884c8515929",
      "name": "Generate Refresh Token from authcode",
      "type": "n8n-nodes-base.httpRequest",
      "maxTries": 2,
      "position": [
        820,
        -560
      ],
      "parameters": {
        "url": "https://oauth.pipedrive.com/oauth/token",
        "method": "POST",
        "options": {
          "response": {
            "response": {
              "fullResponse": true
            }
          }
        },
        "sendBody": true,
        "contentType": "form-urlencoded",
        "sendHeaders": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "grant_type",
              "value": "authorization_code"
            },
            {
              "name": "code",
              "value": "={{$node[\"catch Auth code\"].json[\"query\"][\"code\"]}}"
            },
            {
              "name": "redirect_uri",
              "value": "={{ $node[\"catch Auth code\"].json[\"webhookUrl\"] }}"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "={{$node[\"convert clientId and secret to base64\"].json[\"authheader\"]}}"
            }
          ]
        }
      },
      "retryOnFail": false,
      "typeVersion": 4,
      "alwaysOutputData": false
    },
    {
      "id": "9c1b22e1-fd50-4c70-91cf-f4ea8cc7d3ac",
      "name": "Look for the related record in Supabase",
      "type": "n8n-nodes-base.supabase",
      "position": [
        1060,
        -540
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "Platform",
              "keyValue": "Pipedrive"
            }
          ]
        },
        "tableId": "App_tok",
        "operation": "get"
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "53602a58-d47a-4133-b9ec-4ea421a75eea",
      "name": "IF rec not found",
      "type": "n8n-nodes-base.if",
      "position": [
        1260,
        -540
      ],
      "parameters": {
        "conditions": {
          "number": [
            {
              "value1": "={{ $json.values().length }}",
              "operation": "equal"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "38e5d91c-1bea-4f7a-8336-98748005d02e",
      "name": "Update tokns in the record",
      "type": "n8n-nodes-base.supabase",
      "position": [
        1600,
        -460
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "Platform",
              "keyValue": "Pipedrive",
              "condition": "eq"
            }
          ]
        },
        "tableId": "App_tok",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "acc_token",
              "fieldValue": "={{ $node[\"Generate Refresh Token from authcode\"].json[\"body\"][\"access_token\"] }}"
            },
            {
              "fieldId": "ref_token",
              "fieldValue": "={{ $node[\"Generate Refresh Token from authcode\"].json[\"body\"][\"refresh_token\"] }}"
            },
            {
              "fieldId": "updated_at",
              "fieldValue": "={{$now.toUTC().toString()}}"
            }
          ]
        },
        "matchType": "allFilters",
        "operation": "update"
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "43a2613d-7793-48c9-8934-57d9b713f5fe",
      "name": "Supabase- look for the record",
      "type": "n8n-nodes-base.supabase",
      "position": [
        600,
        -140
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "Platform",
              "keyValue": "Pipedrive"
            },
            {
              "keyName": "AppId",
              "keyValue": "={{ $node[\"Webhook\"].json[\"body\"][\"appId\"] }}"
            }
          ]
        },
        "tableId": "App_tok",
        "operation": "get"
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "366bd343-419c-4a77-b2ce-e6124a6cc291",
      "name": "combine client id and secret",
      "type": "n8n-nodes-base.set",
      "position": [
        840,
        -140
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "4330b857-6184-4ad8-82dc-a8b806ab8077",
              "name": "authheader",
              "type": "string",
              "value": "57db0bab2932f657:YOUR_AWS_SECRET_KEY_HERE"
            }
          ]
        }
      },
      "typeVersion": 3.3
    },
    {
      "id": "156acb8f-3a23-40ec-b011-9db8bfa6d98b",
      "name": "Get Pipedrive acess token",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1060,
        -140
      ],
      "parameters": {
        "url": "https://oauth.pipedrive.com/oauth/token",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "form-urlencoded",
        "sendHeaders": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "grant_type",
              "value": "refresh_token"
            },
            {
              "name": "refresh_token",
              "value": "={{ $node[\"Supabase- look for the record\"].json[\"ref_token\"] }}"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Basic {{ $json[\"authheader\"].base64Encode() }}"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "3e20309e-6d50-444c-b9e1-cf6d6982e546",
      "name": "IF success",
      "type": "n8n-nodes-base.if",
      "position": [
        1240,
        -140
      ],
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{ Object.keys($input.first().json)[0]}}",
              "value2": "access_token"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "1e991aa7-9888-404d-8f80-bb6ce0a3b777",
      "name": "Update thr row with new access token",
      "type": "n8n-nodes-base.supabase",
      "position": [
        1420,
        -280
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "Platform",
              "keyValue": "Pipedrive",
              "condition": "eq"
            }
          ]
        },
        "tableId": "App_tok",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "acc_token",
              "fieldValue": "={{ $node[\"Get Pipedrive acess token\"].json[\"access_token\"] }}"
            },
            {
              "fieldId": "ref_token",
              "fieldValue": "={{ $node[\"Get Pipedrive acess token\"].json[\"refresh_token\"] }}"
            }
          ]
        },
        "matchType": "allFilters",
        "operation": "update"
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "d0989bad-9176-44a2-86ce-db07a5e8a34c",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        340,
        -140
      ],
      "parameters": {
        "path": "937a8843-a28a-400a-b473-bdc598366fa0",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "lastNode",
        "authentication": "basicAuth"
      },
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "108a2ea1-de2a-4df3-9d9f-0ce1b27a52e9",
      "name": "Receive request",
      "type": "n8n-nodes-base.webhook",
      "position": [
        280,
        680
      ],
      "parameters": {
        "path": "47704458-bfa6-4d95-adf1-97fc78e35d8a",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode",
        "authentication": "basicAuth"
      },
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "f983cfd1-52db-4839-88af-6386ec7c7256",
      "name": "catch Auth code",
      "type": "n8n-nodes-base.webhook",
      "position": [
        300,
        -560
      ],
      "parameters": {
        "path": "aae545fb-a69d-4e20-91ce-65f105d0ea2f",
        "options": {}
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "callerPolicy": "workflowsFromSameOwner",
    "executionOrder": "v1",
    "saveManualExecutions": true
  },
  "versionId": "54499ed8-4677-400a-9e03-d0d84f8a97b5",
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Supabase- look for the record",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF success": {
      "main": [
        [
          {
            "node": "Update thr row with new access token",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Stop and Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Receive request": {
      "main": [
        [
          {
            "node": "Get Pipedrive Token",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "catch Auth code": {
      "main": [
        [
          {
            "node": "convert clientId and secret to base64",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF rec not found": {
      "main": [
        [
          {
            "node": "Insert",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Update tokns in the record",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Pipedrive Token": {
      "main": [
        [
          {
            "node": "Get contact from Pipedrive",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Access Token Invalid": {
      "main": [
        [
          {
            "node": "Refresh Access Token",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Success",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Refresh Access Token": {
      "main": [
        [
          {
            "node": "Get Pipedrive Token",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Pipedrive acess token": {
      "main": [
        [
          {
            "node": "IF success",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get contact from Pipedrive": {
      "main": [
        [
          {
            "node": "Access Token Invalid",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "combine client id and secret": {
      "main": [
        [
          {
            "node": "Get Pipedrive acess token",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Supabase- look for the record": {
      "main": [
        [
          {
            "node": "combine client id and secret",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Refresh Token from authcode": {
      "main": [
        [
          {
            "node": "Look for the related record in Supabase",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "convert clientId and secret to base64": {
      "main": [
        [
          {
            "node": "Generate Refresh Token from authcode",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Look for the related record in Supabase": {
      "main": [
        [
          {
            "node": "IF rec not found",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This workflow provides an OAuth 2.0 auth token refresh process for better control. Developers can utilize it as an alternative to n8n's built-in OAuth flow to achieve improved control and visibility. In this template, I've used Pipedrive API, but users can apply it with any app…

Source: https://n8n.io/workflows/2319/ — original creator credit. Request a take-down →

More Data & Sheets workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Data & Sheets

2. Refresh Pipedrive tokens. Uses stopAndError, stickyNote, supabase, httpRequest. Webhook trigger; 29 nodes.

Stop And Error, Supabase, HTTP Request
Data & Sheets

This solution enables you to manage all your Notion and Todoist tasks from different workspaces as well as your calendar events in a single place. This is 2 way sync with partial support for recurring

Redis, Notion, Todoist +6
Data & Sheets

Notion to Clockify Sync Template. Uses scheduleTrigger, clockify, compareDatasets, stopAndError. Webhook trigger; 68 nodes.

Clockify, Stop And Error, Notion +1
Data & Sheets

This workflow synchronizes three entities from Notion to Clockify, allowing tracked time to be linked to client-related projects or tasks.

Clockify, Stop And Error, Notion +1
Data & Sheets

Ai Assistant Workflow. Uses supabase, httpRequest, emailSend. Webhook trigger; 14 nodes.

Supabase, HTTP Request, Email Send