# Code Mode

- **URL:** https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode
- **Summary:** Code Mode lets you write JavaScript to fully customize an OAuth request when the form builder isn't flexible enough. Instead of filling in fields for the URL, headers, params, and body, you write a short script that builds the request (or the authorization URL), runs it, and returns the result.

[Skip to main content](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#__docusaurus_skipToContent_fallback)

Version: v3

On this page

Code Mode lets you write JavaScript to fully customize an OAuth request when the form builder isn't flexible enough. Instead of filling in fields for the URL, headers, params, and body, you write a short script that builds the request (or the authorization URL), runs it, and returns the result.

Reach for Code Mode when you need to do things the form can't express, such as:

*   Building a request signature or hash (HMAC, SHA-256).
*   Assembling a non-standard request body or dynamic query string.
*   Parsing or reshaping the provider's response before HighLevel stores it.
*   Conditional logic that depends on the user's input or the provider's response.

You can switch any supported request between form mode and Code Mode at any time using **Switch to Code Mode** / **Switch to Form Mode**.

Which requests support Code Mode[​](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#which-requests-support-code-mode "Direct link to Which requests support Code Mode")

Code Mode is available on the following [OAuth 2.0](https://marketplace.gohighlevel.com/docs/oauth/external-auth/OAuth2)
 requests:

| Step | Internal name | What your script returns |
| --- | --- | --- |
| Authorization URL | `authorizationUrl` | A URL **string** to send the user to. |
| Access token request | `accessTokenRequest` | The token response object (`access_token`, `refresh_token`, ...). |
| Refresh token request | `refreshTokenRequest` | The refreshed token response object. |
| Test API endpoint | `testRequest` | The HTTP response (used to confirm the token works). |
| Fetch user info | `userInfoRequest` | The user/account info response (then field-mapped). |

Switching to Code Mode[​](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#switching-to-code-mode "Direct link to Switching to Code Mode")

When you click **Switch to Code Mode**, HighLevel pre-fills the editor with a starter template for that step. The template mirrors a typical request so you can edit it rather than start from scratch.

> The handlebars template variables you use in form mode (`{{externalApp.clientId}}`, `{{bundle.code}}`, etc.) are **not** used in Code Mode. Instead you access the same data through the JavaScript objects described below (`process.env`, `bundle`).

The execution environment[​](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#the-execution-environment "Direct link to The execution environment")

Your script runs inside a secure, isolated JavaScript sandbox. The following globals are available.

### `bundle`[​](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#bundle "Direct link to bundle")

Holds the current authentication state and inputs for the step.

    bundle.inputData   // inputs for this step (see per-step table below)bundle.authData    // the stored token data (on refresh / user info steps)

**`bundle.inputData`** contains, depending on the step:

| Property | Available in | Description |
| --- | --- | --- |
| `state` | authorization, access token | The OAuth `state` value generated by HighLevel. |
| `redirect_uri` | authorization, access token | The OAuth redirect URL. |
| `code` | access token | The authorization code returned by your provider. |
| `code_verifier` | access token (PKCE) | The PKCE code verifier (also auto-attached to the request body for you). |
| `<your field keys>` | all | Any values the user entered for your [configured fields](https://marketplace.gohighlevel.com/docs/oauth/external-auth/ConfigureYourFields)<br>. |

**`bundle.authData`** contains the stored token data, used when refreshing or fetching user info:

    bundle.authData.access_tokenbundle.authData.refresh_token// plus any other top-level fields returned by your token response

### `process.env`[​](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#processenv "Direct link to processenv")

A frozen, read-only object with your app credentials:

    process.env.CLIENT_ID      // your OAuth Client IDprocess.env.CLIENT_SECRET  // your OAuth Client Secret (empty when using PKCE only)process.env.SCOPES         // the configured scopes

### `z` - the helper namespace[​](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#z---the-helper-namespace "Direct link to z---the-helper-namespace")

A frozen object with everything you need to make requests and work with data.

#### `z.request(options)`[​](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#zrequestoptions "Direct link to zrequestoptions")

Makes an outbound HTTP request and returns a promise resolving to the response. Options:

    const options = {  url: 'https://api.example.com/oauth/token',  method: 'POST',                          // GET, POST, PUT, PATCH, DELETE, HEAD  headers: { 'content-type': 'application/x-www-form-urlencoded' },  params: { /* query string params */ },  body: { /* request body */ },  removeMissingValuesFrom: {               // drop empty params/body keys    body: false,    params: false  }}

The resolved response has this shape:

    {  status,    // HTTP status code (number)  headers,   // response headers  content,   // raw response body as a string  data,      // parsed body (object if JSON, otherwise the raw value)  json       // the JSON-parsed body (or the raw value if not JSON)}

> When `content-type` is `application/x-www-form-urlencoded`, the `body` object is automatically form-encoded for you.

#### `z.console`[​](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#zconsole "Direct link to zconsole")

Logging that appears in the tester's **Logs** tab. Use it to debug your script.

    z.console.log('exchanging code', bundle.inputData.code)

A plain `console.log(...)` also works and writes to the same place.

#### `z.errors.RefreshAuthError`[​](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#zerrorsrefreshautherror "Direct link to zerrorsrefreshautherror")

Throw this from the access token or refresh token step to signal that the credentials are no longer valid and a refresh/re-auth is required.

    throw new z.errors.RefreshAuthError('Token rejected by provider')

#### `z.require(...)`[​](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#zrequire "Direct link to zrequire")

A small set of built-in helpers is available:

    const qs = z.require('querystring')   // stringify / parse / escape / unescapeconst crypto = z.require('crypto')    // createHash(algo).update(v).digest(enc), randomBytes(n).toString(enc)

    const sig = z.require('crypto').createHash('sha256').update(raw).digest('hex')const query = z.require('querystring').stringify({ a: 1, b: 2 }) // "a=1&b=2"

Other modules are not available and will throw an error.

`z.JSON` is also exposed (equivalent to the standard `JSON` object).

What your script must return[​](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#what-your-script-must-return "Direct link to What your script must return")

*   **Authorization URL step** - `return` a URL **string**. It must be a valid `https` URL.
*   **All other steps** - `return z.request(options)` (or a promise that resolves to the response/parsed object). You can parse or reshape the response in a `.then()` before returning it.

Examples[​](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#examples "Direct link to Examples")

### Authorization URL[​](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#authorization-url "Direct link to Authorization URL")

    const url = `https://example.com/oauth/authorize?client_id=${process.env.CLIENT_ID}&state=${bundle.inputData.state}&redirect_uri=${encodeURIComponent(bundle.inputData.redirect_uri)}&response_type=code`;return url;

### Access token request[​](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#access-token-request "Direct link to Access token request")

    const options = {  url: 'https://api.example.com/oauth/token',  method: 'POST',  headers: {    'content-type': 'application/x-www-form-urlencoded',    'accept': 'application/json'  },  params: {},  body: {    'code': bundle.inputData.code,    'client_id': process.env.CLIENT_ID,    'client_secret': process.env.CLIENT_SECRET,    'grant_type': 'authorization_code',    'redirect_uri': bundle.inputData.redirect_uri  },  removeMissingValuesFrom: { 'body': false, 'params': false }}return z.request(options)  .then((response) => {    const results = response.json;    // Reshape results here if your provider's response differs.    return results;  });

### Refresh token request[​](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#refresh-token-request "Direct link to Refresh token request")

    const options = {  url: 'https://api.example.com/oauth/token',  method: 'POST',  headers: {    'content-type': 'application/x-www-form-urlencoded',    'accept': 'application/json'  },  params: {},  body: {    'refresh_token': bundle.authData.refresh_token,    'grant_type': 'refresh_token'  },  removeMissingValuesFrom: { 'body': false, 'params': false }}return z.request(options).then((response) => response.json);

### Test request[​](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#test-request "Direct link to Test request")

    const options = {  url: 'https://api.example.com/me',  method: 'GET',  headers: {},  params: {},  removeMissingValuesFrom: { 'body': false, 'params': false }}return z.request(options).then((response) => response.json);

### Fetch user info[​](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#fetch-user-info "Direct link to Fetch user info")

    const options = {  url: 'https://api.example.com/me',  method: 'GET',  headers: {    'authorization': `Bearer ${bundle.authData.access_token}`,    'accept': 'application/json'  },  params: {},  removeMissingValuesFrom: { 'body': false, 'params': false }}return z.request(options).then((response) => response.json);

The returned object is then field-mapped using the **ID / Name / Email** paths you configure in [Multi-Account Support & User Info](https://marketplace.gohighlevel.com/docs/oauth/external-auth/MultiAccountSupport)
.

Limits & restrictions[​](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#limits--restrictions "Direct link to Limits & restrictions")

Code Mode runs in a sandbox with guardrails to keep it safe and fast:

*   **HTTPS only** - all `z.request()` calls must use `https://` URLs.
*   **No internal/private networks** - requests to localhost, private IP ranges, and internal hostnames are blocked.
*   **Execution timeout** - scripts that run too long (around 25 seconds) are aborted.
*   **Size limits** - there are limits on script size and on the size of the response a request may return.
*   **Limited modules** - only `querystring` and `crypto` (via `z.require`) plus standard JavaScript built-ins are available.
*   **Restricted headers** - certain internal headers are not allowed and will cause an error.

### Secret redaction[​](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#secret-redaction "Direct link to Secret redaction")

To protect your credentials, sensitive values - client secrets, access/refresh tokens, authorization codes, the `Authorization` header, cookies - are automatically redacted from the logs and request/response details shown in the tester. You'll see `[REDACTED]` in their place.

Debugging[​](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#debugging "Direct link to Debugging")

Use **Step 3 - Test your auth** to run your script against real values. The tester's **Logs** tab shows your `z.console` output (grouped by step), and the **HTTP Details** tab shows the outbound request and the response. If a script errors or times out, the error message and captured logs are returned so you can fix it.

> Save your configuration before testing - the tester uses the most recently saved version.

Share your feedback
-------------------

★★★★★

*   [Which requests support Code Mode](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#which-requests-support-code-mode)
    
*   [Switching to Code Mode](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#switching-to-code-mode)
    
*   [The execution environment](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#the-execution-environment)
    *   [`bundle`](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#bundle)
        
    *   [`process.env`](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#processenv)
        
    *   [`z` - the helper namespace](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#z---the-helper-namespace)
        
*   [What your script must return](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#what-your-script-must-return)
    
*   [Examples](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#examples)
    *   [Authorization URL](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#authorization-url)
        
    *   [Access token request](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#access-token-request)
        
    *   [Refresh token request](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#refresh-token-request)
        
    *   [Test request](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#test-request)
        
    *   [Fetch user info](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#fetch-user-info)
        
*   [Limits & restrictions](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#limits--restrictions)
    *   [Secret redaction](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#secret-redaction)
        
*   [Debugging](https://marketplace.gohighlevel.com/docs/oauth/external-auth/CodeMode#debugging)
