> ## Documentation Index
> Fetch the complete documentation index at: https://auth0-actions-modules-ga.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> Build your first Auth0 Action Module in the Auth0 Dashboard by creating the module, adding secrets and NPM dependencies, publishing a version, and using it to send logs to an external service.

# Write Your First Action Module

export const AuthCodeGroup = ({children, dropdown}) => {
  const [processedChildren, setProcessedChildren] = useState(children);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      unsubscribe = window.autorun(() => {
        const processChildren = node => {
          if (typeof node === "string") {
            let processedNode = node;
            for (const [key, value] of window.rootStore.variableStore.values.entries()) {
              const escapedKey = key.replaceAll(/[.*+?^${}()|[\]\\]/g, (String.raw)`\$&`);
              processedNode = processedNode.replaceAll(new RegExp(escapedKey, "g"), value);
            }
            return processedNode;
          } else if (Array.isArray(node)) {
            return node.map(processChildren);
          } else if (node && node.props && node.props.children) {
            return {
              ...node,
              props: {
                ...node.props,
                children: processChildren(node.props.children)
              }
            };
          }
          return node;
        };
        setProcessedChildren(processChildren(children));
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  return <CodeGroup dropdown={dropdown}>{processedChildren}</CodeGroup>;
};

## Get Started

Use the quickstart to write an Action Module and use it from an Action to send logs to an external service.

<Steps>
  <Step title="Create an Action Module" titleSize="h3" stepNumber={1}>
    To use an Action Module from a specific Action, you first need to create the Action Module and then add/use it in an Action.

    <Tabs>
      <Tab title="Dashboard">
        1. Navigate to [Auth0 Dashboard > Actions > Library](https://manage.auth0.com/#/actions/library) then select **Modules**.
        2. Select **Create Module**.
        3. Enter a **Name**.
        4. Select **Create**.

        Auth0 displays the Code Editor

        <Frame>
          <img src="https://mintlify.s3.us-west-1.amazonaws.com/auth0-actions-modules-ga/docs/images/customize/actions/modules/actions-modules-new-module.png" alt="Actions Modules - New Action Module" />
        </Frame>
      </Tab>

      <Tab title="Management API">
        1. [Get a Management API Access Token](/docs/secure/tokens/access-tokens/management-api-access-tokens) with the `create:actions` scope.
        2. Call [Create an Actions Module](https://auth0.com/docs/api/management/v2/actions/post-action-module):

        ```shell lines theme={null}
        curl -L 'https://{yourDomain}/api/v2/actions/modules' \
          -H 'Content-Type: application/json' \
          -H 'Authorization: Bearer {yourMgmtApiAccessToken}' \
          -d '{
            "name": "logger",
            "code": "module.exports = {};",
            "api_version": "1",
            "publish": false
          }'
        ```

        Auth0 returns the new Action Module, including its `id`, which you use to reference the module in later steps.
      </Tab>

      <Tab title="Auth0 CLI">
        <Note>
          Actions Modules are not natively exposed by the `auth0-cli` command set, so use [`auth0 api`](https://auth0.github.io/auth0-cli/auth0_api.html) to call the Management API directly. Some calls require additional scopes — run `auth0 login --scopes create:actions,read:actions,update:actions` first if needed.
        </Note>

        Call [Create an Actions Module](https://auth0.com/docs/api/management/v2/actions/post-action-module) with `auth0 api`:

        ```shell lines theme={null}
        auth0 api post actions/modules --data '{
          "name": "logger",
          "code": "module.exports = {};",
          "api_version": "1",
          "publish": false
        }'
        ```

        Auth0 returns the new Action Module, including its `id`, which you use to reference the module in later steps.
      </Tab>

      <Tab title="Terraform">
        <Note>
          Read the [`auth0_action_module`](https://registry.terraform.io/providers/auth0/auth0/latest/docs/resources/action_module) resource documentation to learn more.
        </Note>

        1. Add the following resource to a `.tf` file, referencing the module's code from a file:

        ```terraform lines theme={null}
        resource "auth0_action_module" "logger" {
          name = "logger"
          code = file("${path.module}/action-modules/logger/code.js")
        }
        ```

        2. Create the module's code file at `action-modules/logger/code.js`:

        ```javascript lines theme={null}
        module.exports = {};
        ```

        3. Run `terraform apply`.

        You will expand the code file and this resource with secrets in the following steps.
      </Tab>

      <Tab title="Auth0 Deploy CLI">
        <Note>
          Actions Modules is an Early Access feature. Run the Deploy CLI with the `--experimental_ea` flag to manage it.
        </Note>

        <Tabs>
          <Tab title="YAML">
            1. Create the module's code file at `action-modules/logger/code.js`:

            ```javascript lines theme={null}
            module.exports = {};
            ```

            2. Add an `actionModules` entry to `tenant.yaml`:

            ```yaml lines theme={null}
            actionModules:
              - name: logger
                code: ./action-modules/logger/code.js
            ```

            3. Deploy the configuration:

            ```shell lines theme={null}
            a0deploy import -c=config.json --input_file=tenant.yaml --experimental_ea
            ```
          </Tab>

          <Tab title="Directory (JSON)">
            1. Create the module's configuration file at `action-modules/logger.json`:

            ```json lines theme={null}
            {
              "name": "logger",
              "code": "./action-modules/logger/code.js"
            }
            ```

            2. Create the module's code file at `action-modules/logger/code.js`:

            ```javascript lines theme={null}
            module.exports = {};
            ```

            3. Deploy the configuration:

            ```shell lines theme={null}
            a0deploy import -c=config.json --input_file=. --experimental_ea
            ```
          </Tab>
        </Tabs>
      </Tab>
    </Tabs>
  </Step>

  <Step title="Add a Secret" titleSize="h3" stepNumber={2}>
    Each Action Module can contain secret key/values pairs. Use these to hold sensitive information, such as API Keys, certificates, and values that may change across environments.

    <Tabs>
      <Tab title="Dashboard">
        Let’s store the external service URL as a Secret.

        1. Select the **<svg style={{ display: 'inline' }} width="20" height="20" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg" class="sc-kJNqSH"><path fill-rule="evenodd" clip-rule="evenodd" d="M19.573 2.06l1.409 1.42-1.192 1.182L22.65 7.5l-4.756 4.72-2.86-2.838-2.783 2.764a6.196 6.196 0 011.196 3.63 6.172 6.172 0 01-1.832 4.41 6.277 6.277 0 01-8.853-.03l-.007-.008A6.183 6.183 0 011 15.782a6.184 6.184 0 011.831-4.335 6.271 6.271 0 017.987-.696l8.755-8.691zm-9.335 10.798l-.045-.043a4.264 4.264 0 00-2.987-1.182 4.262 4.262 0 00-2.966 1.233A4.184 4.184 0 003 15.8a4.183 4.183 0 001.185 2.95 4.276 4.276 0 006.022.016 4.2 4.2 0 001.24-2.984 4.171 4.171 0 00-1.21-2.924zm6.216-4.885l1.44 1.43L19.811 7.5l-1.44-1.43-1.917 1.903z" fill="inherit" /></svg>** icon from the code editor's left sidebar.
        2. Select **Add Secret**.
        3. Enter the **Name** as `SERVICE_URL`.
        4. Enter the external service URL at the **Value** field.
        5. Select **Create**.

        <Frame>
          <img src="https://mintlify.s3.us-west-1.amazonaws.com/auth0-actions-modules-ga/docs/images/customize/actions/modules/actions-modules-secret.png" alt="Actions Modules - Secret added" />
        </Frame>

        Auth0 adds the Secret to the Action Module Secret list.
      </Tab>

      <Tab title="Management API">
        Let’s store the external service URL as a Secret. Call [Update an Actions Module](https://auth0.com/docs/api/management/v2/actions/patch-action-module) with the `update:actions` scope:

        ```shell lines theme={null}
        curl -L -X PATCH 'https://{yourDomain}/api/v2/actions/modules/{moduleId}' \
          -H 'Content-Type: application/json' \
          -H 'Authorization: Bearer {yourMgmtApiAccessToken}' \
          -d '{
            "secrets": [
              { "name": "SERVICE_URL", "value": "https://example.com/logs" }
            ]
          }'
        ```

        Each `PATCH` call replaces the entire `secrets` array on the module's draft, so include every Secret the module needs, not just the one you are adding.
      </Tab>

      <Tab title="Auth0 CLI">
        Let’s store the external service URL as a Secret. Call [Update an Actions Module](https://auth0.com/docs/api/management/v2/actions/patch-action-module) with `auth0 api`:

        ```shell lines theme={null}
        auth0 api patch actions/modules/{moduleId} --data '{
          "secrets": [
            { "name": "SERVICE_URL", "value": "https://example.com/logs" }
          ]
        }'
        ```

        Each call replaces the entire `secrets` array on the module's draft, so include every Secret the module needs, not just the one you are adding.
      </Tab>

      <Tab title="Terraform">
        Let’s store the external service URL as a Secret using a `secrets` block:

        ```terraform lines theme={null}
        resource "auth0_action_module" "logger" {
          name = "logger"
          code = file("${path.module}/action-modules/logger/code.js")

          secrets {
            name  = "SERVICE_URL"
            value = "https://example.com/logs"
          }
        }
        ```

        <Note>
          Partial management of `secrets` is not supported — each `terraform apply` sends the complete list of secrets defined on the resource.
        </Note>
      </Tab>

      <Tab title="Auth0 Deploy CLI">
        Let’s store the external service URL as a Secret.

        <Tabs>
          <Tab title="YAML">
            Add a `secrets` array to the module's entry in `tenant.yaml`:

            ```yaml lines highlight={3-5} theme={null}
            actionModules:
              - name: logger
                secrets:
                  - name: SERVICE_URL
                    value: ##SERVICE_URL##
                code: ./action-modules/logger/code.js
            ```
          </Tab>

          <Tab title="Directory (JSON)">
            Add a `secrets` array to `action-modules/logger.json`:

            ```json lines highlight={3-5} theme={null}
            {
              "name": "logger",
              "secrets": [
                { "name": "SERVICE_URL", "value": "##SERVICE_URL##" }
              ],
              "code": "./action-modules/logger/code.js"
            }
            ```
          </Tab>
        </Tabs>

        The `##SERVICE_URL##` placeholder is resolved through [keyword replacement](https://github.com/auth0/auth0-deploy-cli/blob/master/docs/keyword-replacement.md) at deploy time, so the actual value never lives in your configuration file.
      </Tab>
    </Tabs>

    **Extra Step:** Repeat the steps to store an `API_KEY` as a Secret that you will send in the headers to the external service in each request.

    <Callout icon="file-lines" color="#0EA5E9" iconType="regular">
      Once you create a Secret, Auth0 never reveals its value. Auth0 encrypts all Secrets and stores them securely.
    </Callout>

    <Warning>
      Each **Action Module Secret** is independent from other **Actions Modules** and **Actions Secrets**.
    </Warning>

    <Callout icon="file-lines" color="#0EA5E9" iconType="regular">
      Use **Secrets** at the Action Module by typing `actions.secrets.[secret_key]`.
    </Callout>
  </Step>

  <Step title="Add Custom Logic" titleSize="h3" stepNumber={3}>
    Now, add the following code to your Action Module.

    <Tabs>
      <Tab title="Dashboard">
        Add the following code to your Action Module:

        ```javascript lines theme={null}
        module.exports = {
          sendLog: async (code, message) => {
            try {
              await fetch(actions.secrets.SERVICE_URL, {
                method: 'POST',
                headers: {
                  'X-API-Key': actions.secrets.API_KEY,
                },
                body: JSON.stringify({
                  code,
                  message
                }),
              });

              console.log({
                code,
                message
              });
            } catch (err) {
              throw new Error('External service failure');
            }

            return;
          }
        };
        ```
      </Tab>

      <Tab title="Management API">
        Call [Update an Actions Module](https://auth0.com/docs/api/management/v2/actions/patch-action-module) with the following request:

        ```shell lines theme={null}
        curl -L -X PATCH 'https://{yourDomain}/api/v2/actions/modules/{moduleId}' \
          -H 'Content-Type: application/json' \
          -H 'Authorization: Bearer {yourMgmtApiAccessToken}' \
          -d @code-update.json
        ```

        Where `code-update.json` contains the module's `code` as a JSON-escaped string:

        ```json code-update.json lines theme={null}
        {
          "code": "module.exports = {\n  sendLog: async (code, message) => {\n    try {\n      await fetch(actions.secrets.SERVICE_URL, {\n        method: 'POST',\n        headers: {\n          'X-API-Key': actions.secrets.API_KEY,\n        },\n        body: JSON.stringify({ code, message }),\n      });\n\n      console.log({ code, message });\n    } catch (err) {\n      throw new Error('External service failure');\n    }\n\n    return;\n  }\n};"
        }
        ```
      </Tab>

      <Tab title="Auth0 CLI">
        Save the module's code to `code-update.json`:

        ```json code-update.json lines theme={null}
        {
          "code": "module.exports = {\n  sendLog: async (code, message) => {\n    try {\n      await fetch(actions.secrets.SERVICE_URL, {\n        method: 'POST',\n        headers: {\n          'X-API-Key': actions.secrets.API_KEY,\n        },\n        body: JSON.stringify({ code, message }),\n      });\n\n      console.log({ code, message });\n    } catch (err) {\n      throw new Error('External service failure');\n    }\n\n    return;\n  }\n};"
        }
        ```

        Then pipe it into [Update an Actions Module](https://auth0.com/docs/api/management/v2/actions/patch-action-module) via `auth0 api`:

        ```shell lines theme={null}
        cat code-update.json | auth0 api patch actions/modules/{moduleId}
        ```
      </Tab>

      <Tab title="Terraform">
        1. Update the module's code file at `action-modules/logger/code.js`:

        ```javascript lines theme={null}
        module.exports = {
          sendLog: async (code, message) => {
            try {
              await fetch(actions.secrets.SERVICE_URL, {
                method: 'POST',
                headers: {
                  'X-API-Key': actions.secrets.API_KEY,
                },
                body: JSON.stringify({
                  code,
                  message
                }),
              });

              console.log({
                code,
                message
              });
            } catch (err) {
              throw new Error('External service failure');
            }

            return;
          }
        };
        ```

        2. The `auth0_action_module` resource's `code` attribute already references this file, so run `terraform apply` to apply the change.
      </Tab>

      <Tab title="Auth0 Deploy CLI">
        Update `action-modules/logger/code.js` with the module's logic:

        ```javascript lines theme={null}
        module.exports = {
          sendLog: async (code, message) => {
            try {
              await fetch(actions.secrets.SERVICE_URL, {
                method: 'POST',
                headers: {
                  'X-API-Key': actions.secrets.API_KEY,
                },
                body: JSON.stringify({
                  code,
                  message
                }),
              });

              console.log({
                code,
                message
              });
            } catch (err) {
              throw new Error('External service failure');
            }

            return;
          }
        };
        ```
      </Tab>
    </Tabs>

    <Callout icon="file-lines" color="#0EA5E9" iconType="regular">
      Be aware of:

      * [Coding Guidelines](/docs/customize/actions/action-coding-guidelines#actions-modules)
      * [Limitations](/docs/customize/actions/limitations#actions-modules)
    </Callout>
  </Step>

  <Step title="Save the Draft" titleSize="h3" stepNumber={4}>
    You can save a draft of your Action Module.

    <Tabs>
      <Tab title="Dashboard">
        1. Select **Save Draft**.

        <Frame>
          <img src="https://mintlify.s3.us-west-1.amazonaws.com/auth0-actions-modules-ga/docs/images/customize/actions/modules/actions-modules-draft.png" alt="Actions Modules - Draft saved" />
        </Frame>
      </Tab>

      <Tab title="Management API">
        There is no separate "save" call. Every [Update an Actions Module](https://auth0.com/docs/api/management/v2/actions/patch-action-module) request in the previous steps already persisted your changes to the module's draft. You can confirm this with [Get an Actions Module](https://auth0.com/docs/api/management/v2/actions/get-action-module):

        ```shell lines theme={null}
        curl -L 'https://{yourDomain}/api/v2/actions/modules/{moduleId}' \
          -H 'Authorization: Bearer {yourMgmtApiAccessToken}'
        ```

        The response's `all_changes_published` field is `false`, confirming the draft has unpublished changes.
      </Tab>

      <Tab title="Auth0 CLI">
        There is no separate "save" call. Every `auth0 api patch actions/modules/{moduleId}` request in the previous steps already persisted your changes to the module's draft. You can confirm this with [Get an Actions Module](https://auth0.com/docs/api/management/v2/actions/get-action-module):

        ```shell lines theme={null}
        auth0 api get actions/modules/{moduleId}
        ```

        The response's `all_changes_published` field is `false`, confirming the draft has unpublished changes.
      </Tab>

      <Tab title="Terraform">
        There is no separate "save" step. The `terraform apply` you ran in the previous steps already updated the module's draft. The draft has no effect on Actions already using a published version of the module.
      </Tab>

      <Tab title="Auth0 Deploy CLI">
        There is no separate "save" step. Leave `all_changes_published` unset (or `false`) on the module's entry and run `a0deploy import` — the Deploy CLI updates the module's draft without publishing a new version.

        <Tabs>
          <Tab title="YAML">
            Leave `all_changes_published` unset (or `false`) on the module's entry in `tenant.yaml`.
          </Tab>

          <Tab title="Directory (JSON)">
            Leave `all_changes_published` unset (or `false`) in `action-modules/logger.json`.
          </Tab>
        </Tabs>
      </Tab>
    </Tabs>

    This saves your Action Module without publishing a new version, so it does not affect Actions using it.
  </Step>

  <Step title="Publish the Action Module" titleSize="h3" stepNumber={5}>
    Once you are satisfied with the Action Module code, it’s time to **Publish** it.

    <Tabs>
      <Tab title="Dashboard">
        1. Select **Publish**.

        <Callout icon="file-lines" color="#0EA5E9" iconType="regular">
          Publishing an Action Module takes a snapshot of it at that time and records it as an **Action Module Version**.
        </Callout>

        2. Select **View Version History**.

        <Frame>
          <img src="https://mintlify.s3.us-west-1.amazonaws.com/auth0-actions-modules-ga/docs/images/customize/actions/modules/actions-modules-published-version.png" alt="Actions Modules - Version History" />
        </Frame>

        Auth0 displays the list of Action Module Versions including the draft.
      </Tab>

      <Tab title="Management API">
        Call [Create an Actions Module Version](https://auth0.com/docs/api/management/v2/actions/post-action-module-version), which takes a snapshot of the current draft and publishes it:

        ```shell lines theme={null}
        curl -L -X POST 'https://{yourDomain}/api/v2/actions/modules/{moduleId}/versions' \
          -H 'Authorization: Bearer {yourMgmtApiAccessToken}'
        ```

        Auth0 returns the new **Action Module Version**, including its `id` and `version_number`. You'll reference this `id` as the `module_version_id` when adding the module to an Action.
      </Tab>

      <Tab title="Auth0 CLI">
        Call [Create an Actions Module Version](https://auth0.com/docs/api/management/v2/actions/post-action-module-version) with `auth0 api`, which takes a snapshot of the current draft and publishes it:

        ```shell lines theme={null}
        auth0 api post actions/modules/{moduleId}/versions
        ```

        Auth0 returns the new **Action Module Version**, including its `id` and `version_number`. You'll reference this `id` as the `module_version_id` when adding the module to an Action.
      </Tab>

      <Tab title="Terraform">
        Set `publish` to `true` on the resource, then run `terraform apply`:

        ```terraform lines highlight={4} theme={null}
        resource "auth0_action_module" "logger" {
          name    = "logger"
          code    = file("${path.module}/action-modules/logger/code.js")
          publish = true

          secrets {
            name  = "SERVICE_URL"
            value = "https://example.com/logs"
          }
        }
        ```

        Publishing creates a new **Action Module Version** from the current draft. Terraform exposes the published version's ID as the `version_id` computed attribute, which you reference from `auth0_action` resources as `module_version_id`.
      </Tab>

      <Tab title="Auth0 Deploy CLI">
        Set `all_changes_published` to `true` on the module's entry, then redeploy.

        <Tabs>
          <Tab title="YAML">
            Set `all_changes_published` to `true` on the module's entry in `tenant.yaml`:

            ```yaml lines highlight={3} theme={null}
            actionModules:
              - name: logger
                all_changes_published: true
                secrets:
                  - name: SERVICE_URL
                    value: ##SERVICE_URL##
                code: ./action-modules/logger/code.js
            ```

            ```shell lines theme={null}
            a0deploy import -c=config.json --input_file=tenant.yaml --experimental_ea
            ```
          </Tab>

          <Tab title="Directory (JSON)">
            Set `all_changes_published` to `true` in `action-modules/logger.json`:

            ```json lines highlight={2} theme={null}
            {
              "all_changes_published": true,
              "name": "logger",
              "secrets": [
                { "name": "SERVICE_URL", "value": "##SERVICE_URL##" }
              ],
              "code": "./action-modules/logger/code.js"
            }
            ```

            ```shell lines theme={null}
            a0deploy import -c=config.json --input_file=. --experimental_ea
            ```
          </Tab>
        </Tabs>

        The Deploy CLI publishes a new **Action Module Version** from the current draft after applying your changes.
      </Tab>
    </Tabs>

    You are now able to start using the Action Module in an Action.

    <Warning>
      Each **Action** must explicitly reference the **Action Module Version**, preventing automatic upgrades that could introduce unexpected errors.
    </Warning>
  </Step>

  <Step title="Add the Action Module in an Action" titleSize="h3" stepNumber={6}>
    Let’s add the Action Module in an Action.

    <Tabs>
      <Tab title="Dashboard">
        1. Navigate to [Auth0 Dashboard > Actions > Library](https://manage.auth0.com/#/actions/library) then select a specific **Action**.
        2. Once at the Action Editor, select the **<svg style={{ display: 'inline' }} width="20" height="20" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg" class="sc-hQYogJ"><path fill-rule="evenodd" clip-rule="evenodd" d="M9.388 4.07A3.717 3.717 0 0112 3c.977 0 1.917.383 2.612 1.07A3.65 3.65 0 0115.7 6.667a3.65 3.65 0 01-1.028 2.537l1.683 2.778-1.71 1.036-1.701-2.806a3.733 3.733 0 01-3.556-.948A3.65 3.65 0 018.3 6.667c0-.977.393-1.91 1.088-2.597zM12 5c-.455 0-.889.179-1.207.493a1.65 1.65 0 00-.493 1.174c0 .438.176.86.493 1.174.318.314.752.492 1.207.492.455 0 .889-.178 1.207-.492a1.65 1.65 0 00.493-1.174c0-.438-.176-.86-.493-1.174A1.717 1.717 0 0012 5zM6.697 13.802l1.98-2.87 1.646 1.136-1.911 2.77c.633.677.988 1.567.988 2.495a3.65 3.65 0 01-1.088 2.597A3.717 3.717 0 015.7 21a3.717 3.717 0 01-2.612-1.07A3.65 3.65 0 012 17.333c0-.976.393-1.91 1.088-2.597a3.717 3.717 0 013.61-.934zM5.7 15.667c-.455 0-.889.178-1.206.492A1.65 1.65 0 004 17.333c0 .438.176.86.494 1.175.317.313.751.492 1.206.492.455 0 .889-.179 1.206-.492a1.65 1.65 0 00.494-1.175c0-.438-.176-.86-.494-1.174a1.717 1.717 0 00-1.206-.492zM15.688 14.736a3.717 3.717 0 012.612-1.07c.977 0 1.917.384 2.612 1.07A3.65 3.65 0 0122 17.333a3.65 3.65 0 01-1.088 2.597A3.717 3.717 0 0118.3 21a3.717 3.717 0 01-2.612-1.07 3.66 3.66 0 01-.948-1.597H11v-2h3.74c.172-.6.496-1.15.948-1.597zm2.612.93c-.455 0-.889.18-1.207.493a1.65 1.65 0 00-.493 1.174c0 .438.176.86.493 1.175.318.313.752.492 1.207.492.455 0 .889-.179 1.206-.492A1.65 1.65 0 0020 17.332c0-.438-.176-.86-.494-1.174a1.717 1.717 0 00-1.206-.492z" fill="inherit" /></svg>** icon from the left sidebar.
        3. Select **Add Module**.
        4. Select a Module **Name** and **Version**.
        5. Select **Add**.

        <Frame>
          <img src="https://mintlify.s3.us-west-1.amazonaws.com/auth0-actions-modules-ga/docs/images/customize/actions/modules/actions-modules-add-module.png" alt="Actions - Add Action Module" />
        </Frame>
      </Tab>

      <Tab title="Management API">
        Call [Update an Action](https://auth0.com/docs/api/management/v2/actions/patch-action) with the module's `module_id` and `module_version_id` from the previous step:

        ```shell lines theme={null}
        curl -L -X PATCH 'https://{yourDomain}/api/v2/actions/actions/{actionId}' \
          -H 'Content-Type: application/json' \
          -H 'Authorization: Bearer {yourMgmtApiAccessToken}' \
          -d '{
            "modules": [
              {
                "module_id": "{moduleId}",
                "module_version_id": "{moduleVersionId}"
              }
            ]
          }'
        ```
      </Tab>

      <Tab title="Auth0 CLI">
        <Note>
          [`auth0 actions update`](https://auth0.github.io/auth0-cli/auth0_actions_update.html) has no flag for Action Modules, so call [Update an Action](https://auth0.com/docs/api/management/v2/actions/patch-action) directly with `auth0 api`, using the module's `module_id` and `module_version_id` from the previous step:
        </Note>

        ```shell lines theme={null}
        auth0 api patch actions/actions/{actionId} --data '{
          "modules": [
            {
              "module_id": "{moduleId}",
              "module_version_id": "{moduleVersionId}"
            }
          ]
        }'
        ```
      </Tab>

      <Tab title="Terraform">
        Add a `modules` block to the `auth0_action` resource, referencing the module and its published version. Keep the `code` attribute pointing at the Action's own code file:

        ```terraform lines highlight={3,5-8} theme={null}
        resource "auth0_action" "my_action" {
          name = "my-action"
          code = file("${path.module}/actions/my-action/code.js")

          modules {
            module_id         = auth0_action_module.logger.id
            module_version_id = auth0_action_module.logger.version_id
          }

          supported_triggers {
            id      = "post-login"
            version = "v3"
          }
        }
        ```
      </Tab>

      <Tab title="Auth0 Deploy CLI">
        Add a `modules` array to the Action's configuration, referencing the module by name and version number.

        <Tabs>
          <Tab title="YAML">
            Add the `modules` array to the Action's entry in `tenant.yaml`:

            ```yaml lines highlight={7-9} theme={null}
            actions:
              - name: my-action
                code: ./actions/my-action/code.js
                supported_triggers:
                  - id: post-login
                    version: v3
                modules:
                  - module_name: logger
                    module_version_number: 1
            ```
          </Tab>

          <Tab title="Directory (JSON)">
            Add the `modules` array to the Action's configuration file (for example, `actions/my-action.json`):

            ```json lines highlight={2-5} theme={null}
            {
              "modules": [
                { "module_name": "logger", "module_version_number": 1 }
              ],
              "name": "my-action",
              "code": "./actions/my-action/code.js",
              "supported_triggers": [
                { "id": "post-login", "version": "v3" }
              ]
            }
            ```
          </Tab>
        </Tabs>

        The Deploy CLI resolves `module_name` and `module_version_number` to the module's real `module_id` and `module_version_id` at deploy time.
      </Tab>
    </Tabs>
  </Step>

  <Step title="Use the Action Module in the Action" titleSize="h3" stepNumber={7}>
    Now, let’s use the Action Module in the Action.

    <Tabs>
      <Tab title="Dashboard">
        1. Add the **require** statement.

        ```javascript lines theme={null}
        const logger = require('actions:logger');
        ```

        <Callout icon="file-lines" color="#0EA5E9" iconType="regular">
          The **require** statement references the Action Module with the format **actions:\[module-name]**.
        </Callout>

        2. Add the call to `logger.sendLog` in the **Action function**, where you want to send logs.

        ```javascript lines theme={null}
        await logger.sendLog('logger_success', 'Your Action was able to use the Logger Action Module');
        ```

        3. Select **Deploy** the Action.

        <Frame>
          <img src="https://mintlify.s3.us-west-1.amazonaws.com/auth0-actions-modules-ga/docs/images/customize/actions/modules/actions-modules-use-module.png" alt="Actions - Use Action Module" />
        </Frame>
      </Tab>

      <Tab title="Management API">
        1. Call [Update an Action](https://auth0.com/docs/api/management/v2/actions/patch-action) to add the `require` statement and the call to `logger.sendLog` to the Action's `code`:

        ```shell lines theme={null}
        curl -L -X PATCH 'https://{yourDomain}/api/v2/actions/actions/{actionId}' \
          -H 'Content-Type: application/json' \
          -H 'Authorization: Bearer {yourMgmtApiAccessToken}' \
          -d @code-update.json
        ```

        Where `code-update.json` contains:

        ```json code-update.json lines theme={null}
        {
          "code": "const logger = require('actions:logger');\n\nexports.onExecutePostLogin = async (event, api) => {\n  await logger.sendLog('logger_success', 'Your Action was able to use the Logger Action Module');\n};"
        }
        ```

        2. Call [Deploy an Action](https://auth0.com/docs/api/management/v2/actions/post-deploy-action):

        ```shell lines theme={null}
        curl -L -X POST 'https://{yourDomain}/api/v2/actions/actions/{actionId}/deploy' \
          -H 'Authorization: Bearer {yourMgmtApiAccessToken}'
        ```
      </Tab>

      <Tab title="Auth0 CLI">
        1. Update the Action's code file at `actions/my-action/code.js` with the `require` statement and the call to `logger.sendLog`:

        ```javascript lines theme={null}
        const logger = require('actions:logger');

        exports.onExecutePostLogin = async (event, api) => {
          await logger.sendLog('logger_success', 'Your Action was able to use the Logger Action Module');
        };
        ```

        2. Update the Action with [`auth0 actions update`](https://auth0.github.io/auth0-cli/auth0_actions_update.html) and deploy it with [`auth0 actions deploy`](https://auth0.github.io/auth0-cli/auth0_actions_deploy.html):

        ```shell lines theme={null}
        auth0 actions update {actionId} --code "$(cat actions/my-action/code.js)"
        auth0 actions deploy {actionId}
        ```
      </Tab>

      <Tab title="Terraform">
        1. Update the Action's code file at `actions/my-action/code.js` with the `require` statement and the call to `logger.sendLog`:

        ```javascript lines theme={null}
        const logger = require('actions:logger');

        exports.onExecutePostLogin = async (event, api) => {
          await logger.sendLog('logger_success', 'Your Action was able to use the Logger Action Module');
        };
        ```

        2. Set `deploy` to `true` on the `auth0_action` resource, then run `terraform apply`:

        ```terraform lines highlight={3} theme={null}
        resource "auth0_action" "my_action" {
          name    = "my-action"
          deploy  = true
          code    = file("${path.module}/actions/my-action/code.js")

          modules {
            module_id         = auth0_action_module.logger.id
            module_version_id = auth0_action_module.logger.version_id
          }

          supported_triggers {
            id      = "post-login"
            version = "v3"
          }
        }
        ```

        Setting `deploy = true` immediately creates a new, deployed version of the Action.
      </Tab>

      <Tab title="Auth0 Deploy CLI">
        1. Add the `require` statement and the call to `logger.sendLog` to `actions/my-action/code.js`:

        ```javascript lines theme={null}
        const logger = require('actions:logger');

        exports.onExecutePostLogin = async (event, api) => {
          await logger.sendLog('logger_success', 'Your Action was able to use the Logger Action Module');
        };
        ```

        2. Redeploy the configuration:

        ```shell lines theme={null}
        a0deploy import -c=config.json --input_file=. --experimental_ea
        ```
      </Tab>
    </Tabs>

    <Warning>
      Remember to bind the Action to a Trigger.
    </Warning>
  </Step>
</Steps>

<Check>
  **Checkpoint**

  You should now have a fully functional **Action Module** being used by an **Action**.
</Check>

***

## Advanced Usage

<Accordion title="NPM Dependencies">
  Each **Action Module** can add/use **[NPM Dependencies](https://www.npmjs.com/)**.

  <Tabs>
    <Tab title="Dashboard">
      1. Select the **<svg style={{ display: 'inline' }} width="20" height="20" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg" class="sc-lgWczb"><path fill-rule="evenodd" clip-rule="evenodd" d="M3.543 5.02l7.197-3.715h.003a2.75 2.75 0 012.514 0h.003l7.197 3.715h.002A2.864 2.864 0 0122 7.573v8.853a2.866 2.866 0 01-1.543 2.553l-7.197 3.714a2.75 2.75 0 01-2.529 0l-7.2-3.715-.002-.002A2.865 2.865 0 012 16.413v-8.84A2.865 2.865 0 013.543 5.02zm8.113-1.937l-1.97 1.018L16.5 7.618l2.315-1.195-6.47-3.34h-.001a.75.75 0 00-.688 0zM20 8.063l-7 3.611v8.902l6.542-3.377h.003a.865.865 0 00.455-.774V8.062zM11 20.58v-8.905L4 8.062v8.36a.866.866 0 00.45.778h.001L11 20.58zM5.185 6.423L12 9.94l2.32-1.197-6.815-3.517-2.32 1.197z" fill="inherit" /></svg>** icon from the code editor's left sidebar.
      2. Select **Add Dependency**.
      3. Enter the **Name** of the **NPM package**.
      4. Enter the **Version** of the **NPM package**.
      5. Select **Create**.

      <Frame>
        <img src="https://mintlify.s3.us-west-1.amazonaws.com/auth0-actions-modules-ga/docs/images/customize/actions/modules/actions-modules-dependency.png" alt="Actions Modules - Dependency added" />
      </Frame>

      Auth0 adds the Dependency to the Action Module Dependency list.
    </Tab>

    <Tab title="Management API">
      Call [Update an Actions Module](https://auth0.com/docs/api/management/v2/actions/patch-action-module) with a `dependencies` array:

      ```shell lines theme={null}
      curl -L -X PATCH 'https://{yourDomain}/api/v2/actions/modules/{moduleId}' \
        -H 'Content-Type: application/json' \
        -H 'Authorization: Bearer {yourMgmtApiAccessToken}' \
        -d '{
          "dependencies": [
            { "name": "lodash", "version": "4.17.21" }
          ]
        }'
      ```

      As with `secrets`, each `PATCH` call replaces the entire `dependencies` array, so include every dependency the module needs.
    </Tab>

    <Tab title="Auth0 CLI">
      Call [Update an Actions Module](https://auth0.com/docs/api/management/v2/actions/patch-action-module) with `auth0 api`, using a `dependencies` array:

      ```shell lines theme={null}
      auth0 api patch actions/modules/{moduleId} --data '{
        "dependencies": [
          { "name": "lodash", "version": "4.17.21" }
        ]
      }'
      ```

      As with `secrets`, each call replaces the entire `dependencies` array, so include every dependency the module needs.
    </Tab>

    <Tab title="Terraform">
      Add a `dependencies` block to the `auth0_action_module` resource, then run `terraform apply`:

      ```terraform lines highlight={4-7} theme={null}
      resource "auth0_action_module" "logger" {
        name = "logger"
        code = file("${path.module}/action-modules/logger/code.js")

        dependencies {
          name    = "lodash"
          version = "4.17.21"
        }
      }
      ```
    </Tab>

    <Tab title="Auth0 Deploy CLI">
      Add a `dependencies` array to the module's configuration.

      <Tabs>
        <Tab title="YAML">
          Add the `dependencies` array to the module's entry in `tenant.yaml`:

          ```yaml lines highlight={3-5} theme={null}
          actionModules:
            - name: logger
              dependencies:
                - name: lodash
                  version: 4.17.21
              code: ./action-modules/logger/code.js
          ```
        </Tab>

        <Tab title="Directory (JSON)">
          Add the `dependencies` array to `action-modules/logger.json`:

          ```json lines highlight={2-4} theme={null}
          {
            "dependencies": [
              { "name": "lodash", "version": "4.17.21" }
            ],
            "name": "logger",
            "code": "./action-modules/logger/code.js"
          }
          ```
        </Tab>
      </Tabs>
    </Tab>
  </Tabs>

  <Callout icon="file-lines" color="#0EA5E9" iconType="regular">
    Use the listed **Dependencies** at the Action Module by requiring them through `require('[package-name]')`.
  </Callout>

  <Warning>
    When you save this Action, Auth0 resolves the latest version of your dependency and replaces it with a specific version number to keep future updates to the package from breaking your Action.

    You can provide a specific version instead of latest.
  </Warning>
</Accordion>
