{"id":14957634,"url":"https://github.com/moesif/moesif-nodejs","last_synced_at":"2026-03-27T05:15:01.943Z","repository":{"id":39968340,"uuid":"71393042","full_name":"Moesif/moesif-nodejs","owner":"Moesif","description":"Moesif Node.js middleware (formerly Moesif-Express), for API Monitoring, Analytics, and Monetization.","archived":false,"fork":false,"pushed_at":"2024-11-14T18:27:31.000Z","size":2589,"stargazers_count":43,"open_issues_count":0,"forks_count":26,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-04-04T12:48:31.778Z","etag":null,"topics":["analytics","api-analytics","api-gateway","api-logs","api-management","api-management-api","api-monetization","api-monitoring","express","express-js","koa","logger","logging","nestjs","nextjs","observability","usage-based-billing"],"latest_commit_sha":null,"homepage":"https://www.moesif.com","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Moesif.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-10-19T19:41:10.000Z","updated_at":"2024-12-28T18:30:29.000Z","dependencies_parsed_at":"2023-01-30T16:49:53.067Z","dependency_job_id":"6d4366df-b6cc-4ab6-b364-1fbfba18a873","html_url":"https://github.com/Moesif/moesif-nodejs","commit_stats":{"total_commits":302,"total_committers":21,"mean_commits":"14.380952380952381","dds":0.6026490066225165,"last_synced_commit":"1f04a40dbeb5214b44b428f087fbfdbf768ac6a3"},"previous_names":["moesif/moesif-express"],"tags_count":79,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Moesif%2Fmoesif-nodejs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Moesif%2Fmoesif-nodejs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Moesif%2Fmoesif-nodejs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Moesif%2Fmoesif-nodejs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Moesif","download_url":"https://codeload.github.com/Moesif/moesif-nodejs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247182399,"owners_count":20897381,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["analytics","api-analytics","api-gateway","api-logs","api-management","api-management-api","api-monetization","api-monitoring","express","express-js","koa","logger","logging","nestjs","nextjs","observability","usage-based-billing"],"created_at":"2024-09-24T13:15:16.283Z","updated_at":"2025-11-11T20:06:40.342Z","avatar_url":"https://github.com/Moesif.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Moesif Node.js Middleware Documentation\nby [Moesif](https://moesif.com), the [API analytics](https://www.moesif.com/features/api-analytics) and [API monetization](https://www.moesif.com/solutions/metered-api-billing) platform.\n\n[![NPM](https://nodei.co/npm/moesif-nodejs.png?compact=true\u0026stars=true)](https://nodei.co/npm/moesif-nodejs/)\n\n[![Built For][ico-built-for]][link-built-for]\n[![Total Downloads][ico-downloads]][link-downloads]\n[![Software License][ico-license]][link-license]\n[![Source Code][ico-source]][link-source]\n\nMoesif Node.js middleware automatically logs incoming and outgoing API calls\nand sends them to [Moesif](https://www.moesif.com) for API analytics and monitoring.\nThis middleware allows you to integrate Moesif's API analytics and\nAPI monetization features into your Node.js applications with minimal configuration.\n\n\u003e If you're new to Moesif, see [our Getting Started](https://www.moesif.com/docs/) resources to quickly get up and running.\n\n\n## Notes\n- Previously, this NPM package was called `moesif-express`. In version 3.0, it has been renamed to `moesif-nodejs` to reflect support for any Node.js app.\n- The library can capture both _incoming_ and _outgoing_ API Calls depending on how you configure the SDK. For more information, see [the examples](#examples).\n- To make sure the SDK captures request body, if you use a body parser middleware like `body-parser`, apply Moesif middleware _after_ it.\n\n## Who This Middleware is For\nThe middleware works with REST APIs, [GraphQL APIs](https://www.moesif.com/features/graphql-analytics)\n(such as with [Apollo](https://www.apollographql.com/)), and more.\n\nThis SDK supports any Node.js framework including Express, Koa, and Nest.js. See [the examples](#examples) for more information.\n\n## Prerequisites\nBefore using this middleware, make sure you have the following:\n\n- [An active Moesif account](https://moesif.com/wrap)\n- [A Moesif Application ID](#get-your-moesif-application-id)\n\n### Get Your Moesif Application ID\nAfter you log into [Moesif Portal](https://www.moesif.com/wrap), you can get your Moesif Application ID during the onboarding steps. You can always access the Application ID any time by following these steps from Moesif Portal after logging in:\n\n1. Select the account icon to bring up the settings menu.\n2. Select **Installation** or **API Keys**.\n3. Copy your Moesif Application ID from the **Collector Application ID** field.\n\u003cimg class=\"lazyload blur-up\" src=\"images/app_id.png\" width=\"700\" alt=\"Accessing the settings menu in Moesif Portal\"\u003e\n\n## Install the Middleware\nIn your project directory, install the middleware as a project dependency:\n\n```shell\nnpm install --save moesif-nodejs\n```\n\n## Configure the Middleware\nSee the available [configuration options](#configuration-options) to learn how to configure the middleware for your use case.\n\n## How to Use\n\nThe following step shows how to import Moesif for an example app using Express.js.\n\n### 1. Import the Module\n\n```javascript\n// 1. Import Modules\nvar express = require('express');\nvar app = express();\nvar moesif = require('moesif-nodejs');\n\n// 2. Set the options, the only required field is applicationId.\nvar options = {\n\n  applicationId: 'YOUR_MOESIF_APPLICATION_ID',\n\n  logBody: true,\n\n  identifyUser: function (req, res) {\n    if (req.user) {\n      return req.user.id;\n    }\n    return undefined;\n  },\n\n  getSessionToken: function (req, res) {\n    return req.headers['Authorization'];\n  }\n};\n\n// 3. Initialize the middleware object with options\nvar moesifMiddleware = moesif(options);\n\n\n// 4a. Start capturing outgoing API Calls to 3rd parties like Stripe\n// Skip this step if you don't want to capture outgoing API calls\nmoesifMiddleware.startCaptureOutgoing();\n\n// 4b. Use the Moesif middleware to start capturing incoming API Calls\n// If you have a body parser middleware, apply Moesif middleware after any body parsers.\n// Skip this step if you don't want to capture incoming API calls\napp.use(moesifMiddleware);\n```\nReplace *`YOUR_MOESIF_APPLICATION_ID`* with [your Moesif Application ID](#get-your-moesif-application-id).\n\nIf you are using babel or newer versions of Node.js, you can using more modern syntax for importing—for example, `import moesif from 'moesif-nodejs';` . If you are using ECMAScript modules (ES modules), you can try the following method:\n\n```javascript\nconst moesifImported = await import('moesif-nodejs');\nconst moesif = moesifImported.default;\n```\n\n### 2. Enter Your Moesif Application ID\nThe middleware expects your Moesif Application ID in [the `applicationId` key of the Moesif initialization options object](https://github.com/Moesif/moesif-express-example/blob/a1d94eac8be14a6e52d7d6303d331eae12fc6e99/index.js#L15).\n\nFor instructions on how to obtain your Application ID, see [Get your Moesif Application ID](#get-your-moesif-application-id).\n\nYou can hardcode your Moesif Application ID value in `applicationId`. But we highly recommend that you use a more secure option like environment variables to store your Application ID. If you set the environment variable as `MOESIF_APPLICATION_ID`, Moesif automatically picks it up without you having to explicitly specify it in the `applicationId` key.\n\n```javascript\nvar moesif = require('moesif-nodejs');\nconst http = require('http');\n\nvar options = {\n  applicationId: 'YOUR_MOESIF_APPLICATION_ID',\n  logBody: true,\n};\n\nvar server = http.createServer(function (req, res) {\n  moesif(options)(req, res, function () {\n    // Callback\n  });\n\n  req.on('end', function () {\n\n    res.write(JSON.stringify({\n      message: \"hello world!\",\n      id: 2\n    }));\n    res.end();\n  });\n});\n\nserver.listen(8080);\n\n```\n\nReplace *`YOUR_MOESIF_APPLICATION_ID`* with [your Moesif Application ID](#get-your-moesif-application-id).\n\n### 3. Call your API\n\nFinally, grab the URL to your API endpoint and make some HTTP requests using a tool like Postman or cURL.\n\n## Troubleshoot\nFor a general troubleshooting guide that can help you solve common problems, see [Server Troubleshooting Guide](https://www.moesif.com/docs/troubleshooting/server-troubleshooting-guide/). For troubleshooting issues with capturing outgoing API calls, see [Troubleshoot Capturing Outgoing API Calls](#troubleshoot-outgoing-api-calls-capturing)\n\nOther troubleshooting supports:\n\n- [FAQ](https://www.moesif.com/docs/faq/)\n- [Moesif support email](mailto:support@moesif.com)\n\n### Troubleshoot Capturing Outgoing API Calls\n\nFor instrumenting or capturing outgoing API calls, it instruments standard HTTP or HTTPs from Node.js core.\nHowever, some third party SDKS may use customized HTTP clients to make API calls, which may interfere with instrumentation.\n\nHere are some tips:\n\n- Some SDKS, like the Stripe Node.js SDK, even though they have a very customized http client, lets you swap out to a more standard HTTP client like `node-fetch`.\n\n  ```javascript\n  import fetch from 'node-fetch'; // you may have to add by `npm install node-fetch` or yarn equivalent.\n  import Stripe from 'stripe';\n\n  const stripeClient = Stripe('your secret key', {\n    // basically you are using node fetch as the httpClient.\n    httpClient: Stripe.createFetchHttpClient(fetch),\n  });\n  ```\n\n- Turn `outgoingPatch` flag to `true` in [configuration options](#configuration-options) to make an attempt to cover non-standard HTTP client usage. However, it may not cover all cases.\n\n  ```javascript\n  {\n  const moesifOptions = {\n    // ... other options,\n    outgoingPatch: true\n  };\n  ```\n\n## Repository Structure\n\n```\n.\n├── app.js\n├── dist/\n├── eslint.config.mjs\n├── images/\n├── lib/\n├── LICENSE\n├── package.json\n├── package-lock.json\n├── README.md\n├── test/\n└── tsconfig.json\n```\n\n## Configuration Options\n\n\u003e **Note:** If you're using Koa, you can access the state object through `request.state`.\n\nThe following sections describe the available configuration options for this middleware. You can set these options in the Moesif initialization options object. See [the example Express.js application code](https://github.com/Moesif/moesif-express-example/blob/a1d94eac8be14a6e52d7d6303d331eae12fc6e99/index.js#L15) for an example.\n\n### `logBody`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Default\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eBoolean\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003etrue\u003c/code\u003e\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\nWhether to log request and response body to Moesif.\n\n### `identifyUser`\n\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Parameters\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Return type\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    Function\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003e(req, res)\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eString\u003c/code\u003e\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nA function that takes Express.js [`Request`](https://expressjs.com/en/api.html#req) and [`Response`](https://expressjs.com/en/api.html#res) objects as arguments\nand returns a user ID. This allows Moesif to attribute API requests to individual unique users\nso you can understand who is calling your API. You can use this simultaneously with [`identifyCompany`](#identifycompany)\nto track both individual customers and the companies they are a part of.\n\n```javascript\nvar options = {\n  identifyUser: function (req, res) {\n    // your code here must return the user id as a string. Example Below\n    return req.user ? req.user.id : undefined;\n  }\n}\n```\n\n### `identifyCompany`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Parameters\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Return type\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    Function\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003e(req, res)\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eString\u003c/code\u003e\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nA function that takes Express.js [`Request`](https://expressjs.com/en/api.html#req) and [`Response`](https://expressjs.com/en/api.html#res) objects as arguments\nand returns a company ID. If you have a B2B business, this allows Moesif to attribute\nAPI requests to specific companies or organizations so you can understand which accounts are\ncalling your API. You can use this simultaneously with [`identifyUser`](#identifyuser) to track both\nindividual customers and the companies they are a part of.\n\n\n```javascript\nvar options = {\n  identifyCompany: function (req, res) {\n    // your code here must return the company id as a string. Example Below\n    return req.headers['X-Organization-Id']\n  }\n}\n```\n\n### `getSessionToken`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Parameters\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Return type\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    Function\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003e(req, res)\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eString\u003c/code\u003e\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nA function that takes Express.js [`Request`](https://expressjs.com/en/api.html#req) and [`Response`](https://expressjs.com/en/api.html#res) objects as arguments and returns a\nsession token such as an API key.\n\n\n```javascript\nvar options = {\n  getSessionToken: function (req, res) {\n    // your code here must return a string. Example Below\n    return req.headers['Authorization'];\n  }\n}\n```\n\n### `getApiVersion`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Parameters\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Return type\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    Function\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003e(req, res)\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eString\u003c/code\u003e\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nA function that takes Express.js [`Request`](https://expressjs.com/en/api.html#req) and [`Response`](https://expressjs.com/en/api.html#res) objects as arguments and\nreturns a string to tag requests with a specific version of your API.\n\n```javascript\nvar options = {\n  getApiVersion: function (req, res) {\n    // your code here must return a string. Example Below\n    return req.headers['X-Api-Version']\n  }\n}\n```\n\n### `getMetadata`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Parameters\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Return type\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    Function\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003e(req, res)\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eObject\u003c/code\u003e\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nA function that takes Express.js [`Request`](https://expressjs.com/en/api.html#req) and [`Response`](https://expressjs.com/en/api.html#res) objects as arguments and returns an object.\n\nThis function allows you\nto add custom metadata that Moesif can associate with the request. The metadata must be a simple JavaScript object that can be converted to JSON.\n\nFor example, you may want to save a virtual machine instance ID, a trace ID, or a tenant ID with the request.\n\n\n```javascript\nvar options = {\n  getMetadata: function (req, res) {\n    // your code here:\n    return {\n      foo: 'custom data',\n      bar: 'another custom data'\n    };\n  }\n}\n```\n\n### `skip`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Parameters\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Return type\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    Function\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003e(req, res)\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eBoolean\u003c/code\u003e\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nA function that takes Express.js [`Request`](https://expressjs.com/en/api.html#req) and [`Response`](https://expressjs.com/en/api.html#res) objects as arguments and returns `true`\nif you want to skip the event. Skipping an event means Moesif doesn't log the event.\n\nThe following example skips requests to the root path `/`:\n\n```javascript\nvar options = {\n  skip: function (req, res) {\n    // your code here must return a boolean. Example Below\n    if (req.path === '/' || req.path === '/health') {\n      // Skip logging traffic to root path or health probe.\n      return true;\n    }\n    return false\n  }\n}\n```\n\n### `maskContent`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Parameters\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Return type\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    Function\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003e(MoesifEventModel)\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eMoesifEventModel\u003c/code\u003e\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nA function that takes the final Moesif event model, rather than the Express request or response objects, as an\nargument before the middleware sends the event model object to Moesif.\n\nWith `maskContent`, you can make modifications to headers or body such as\nremoving certain header or body fields.\n\n```javascript\nimport _ from 'lodash';\n\nvar options = {\n  maskContent: function(event) {\n    // remove any field that you don't want to be sent to Moesif.\n    const newEvent = _.omit(event, ['request.headers.Authorization', 'event.response.body.sensitive_field'])\n    return newEvent;\n  }\n};\n```\n\nMoesif's event model format looks like this:\n\n```json\n{\n  \"request\": {\n    \"time\": \"2022-08-08T04:45:42.914\",\n    \"uri\": \"https://api.acmeinc.com/items/83738/reviews/\",\n    \"verb\": \"POST\",\n    \"api_version\": \"1.1.0\",\n    \"ip_address\": \"61.48.220.123\",\n    \"headers\": {\n      \"Host\": \"api.acmeinc.com\",\n      \"Accept\": \"*/*\",\n      \"Connection\": \"Keep-Alive\",\n      \"Content-Type\": \"application/json\",\n      \"Content-Length\": \"126\",\n      \"Accept-Encoding\": \"gzip\"\n    },\n    \"body\": {\n      \"items\": [\n        {\n          \"direction_type\": 1,\n          \"item_id\": \"fwdsfrf\",\n          \"liked\": false\n        },\n        {\n          \"direction_type\": 2,\n          \"item_id\": \"d43d3f\",\n          \"liked\": true\n        }\n      ]\n    }\n  },\n  \"response\": {\n    \"time\": \"2022-08-08T04:45:42.924\",\n    \"status\": 500,\n    \"headers\": {\n      \"Vary\": \"Accept-Encoding\",\n      \"Pragma\": \"no-cache\",\n      \"Expires\": \"-1\",\n      \"Content-Type\": \"application/json; charset=utf-8\",\n      \"Cache-Control\": \"no-cache\"\n    },\n    \"body\": {\n      \"Error\": \"InvalidArgumentException\",\n      \"Message\": \"Missing field location\"\n    }\n  },\n  \"user_id\": \"my_user_id\",\n  \"company_id\": \"my_company_id\",\n  \"session_token\":\"end_user_session_token\",\n  \"tags\": \"tag1, tag2\"\n}\n```\n\nFor more information about the different fields of Moesif's event model,\nsee the following table or the [Moesif Node.js API documentation](https://www.moesif.com/docs/api?javascript).\n\nName | Required | Description\n--------- | -------- | -----------\n`request` | Yes | The object that specifies the API request.\n`request.time`| Yes | Timestamp for the request in ISO 8601 format.\n`request.uri`| Yes | Full URI such as `https://api.com/?query=string` including host, query string, and so on.\n`request.verb`| Yes | The HTTP method—for example, `GET` and `POST`.\n`request.api_version`| No | API Version you want to tag this request with such as `1.0.0`.\n`request.ip_address`| No | IP address of the client. If not set, Moesif uses the IP address of your logging API calls.\n`request.headers`| Yes | Headers of the  request as a `Map\u003cstring, string\u003e` object. Multiple headers with the same key name should be combined together such that the values are joined by a comma. For more information, see [HTTP Header Protocol on w3.org](https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2)\n`request.body`| No | Body of the request in JSON format or base64 encoded binary data. To specify the transfer encoding, use `request.transfer_encoding`.\n`request.transfer_encoding`| No | A string that specifies the transfer encoding of the request body sent to Moesif. If not specified, Moesif assumes the request body assumed to be JSON or text. Only supported value is `base64` for sending binary data like protocol buffers.\n||\n`response` | No | The object that specifies the `response message`. If not set, it implies a null response such as a timeout.\n`response.time`| Yes | Timestamp for the response in ISO 8601 format.\n`response.status`| Yes | HTTP response status code number such as `200 OK` or `500 Internal Server Error`.\n`response.ip_address`| No | IP address of the responding server.\n`response.headers`| Yes | Headers of the response as a `Map\u003cstring, string\u003e` object. Multiple headers with the same key name should be combined together such that the values are joined by a comma. For more information, see [HTTP Header Protocol on w3.org](https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2)\n`response.body`| No | Body of the response in JSON format or base64 encoded binary data. To specify the transfer encoding, use `response.transfer_encoding`\n`response.transfer_encoding`| No | A string that specifies the transfer encoding of the request body sent to Moesif. If not specified, Moesif assumes the body to be JSON or text. Only supported value is `base64` for sending binary data like protocol buffers.\n||\n`session_token` | Recommended | The end user session token such as a JWT or API key, which may or may not be temporary. Moesif automatically detects the session token if not set.\n`user_id` | Recommended | Identifies this API call to a permanent user ID.\n`metadata` | No | A JSON Object consisting of any custom metadata to be stored with this event.\n\n\n### `debug`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Default\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eBoolean\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eundefined\u003c/code\u003e\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nSet to `true` to print debug logs if you're having integration issues.\n\n\n### `isNextJsAppRouter`\n\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Default\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eBoolean\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eundefined\u003c/code\u003e\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nSet to `true` to adapt the interface for NextJs App Router handlers\n\n### `noAutoHideSensitive`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Default\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eBoolean\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003efalse\u003c/code\u003e\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nBefore sending any data for analysis, automatically checks the data (headers and body) and one way\nhash strings or numbers that look like a credit card numbers or passwords. Set\nto `true` if you want to implement your specific [`maskContent`](#maskcontent) function or you want to send all data to be analyzed.\n\n### `callback`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Parameters\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Return type\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    Function\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003e(error)\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003enull\u003c/code\u003e\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nFor for internal errors. For example, if there has been an error sending events\nto Moesif or network issue, you can use this to check for any issues with integration.\n\n### `disableBatching`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Default\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eBoolean\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003efalse\u003c/code\u003e\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nBy default, Moesif Express batches the events. Set to `true` if you want to send the API events one by one.\n\n### `batchSize`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Default\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eNumber\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003e200\u003c/code\u003e\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nIf batching is enabled, this defines the batch size of API events that triggers flushing of queue and sending the data to Moesif. The value of the batch size must be greater than one.\n\n### `batchMaxTime`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Default\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eNumber\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003e2000\u003c/code\u003e\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nIf batching is enabled, this defines the maximum wait time (approximately) in\nmilliseconds before triggering flushing of the queue and sending to Moesif. The\nvalue must be greater than `500` milliseconds.\n\n### `retry`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Default\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eNumber\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003e1\u003c/code\u003e\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nThe number of times to retry the middleware fails to send data to Moesif.\nThe value must be a number between `0` and `3`.\n\n### `requestMaxBodySize`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Default\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eNumber\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003e100000\u003c/code\u003e\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nThe maximum request body size in bytes to log when sending the data to Moesif.\n\n### `responseMaxBodySize`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Default\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eNumber\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003e100000\u003c/code\u003e\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nThe maximum response body size in bytes to log when sending the data to Moesif.\n\n## Capture Outgoing API Calls\n\nIf you want to capture all outgoing API calls from your Node.js app to third parties like\nStripe or to your own dependencies, call `startCaptureOutgoing()` to start capturing.\n\n```javascript\nvar moesifMiddleware = moesif(options);\nmoesifMiddleware.startCaptureOutgoing();\n```\n\nYou can use this method to capture outgoing API calls even if you are not using the Express middleware or having any incoming API calls.\n\nThe same set of [configuration options](#configuration-options) also applies to outgoing API calls, with a few key differences:\n\nThere are several configuration option functions that take request and response objects as arguments. The request and response objects passed into those functions\nare not Express or Node.js request or response objects when the request is outgoing, but Moesif mocks\nsome of the fields for convenience.\n\nOnly a subset of the Node.js request or response fields are available, specifically the following:\n\n### `mo_mocked`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Description\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eBoolean\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    Set to \u003ccode\u003etrue\u003c/code\u003e if it is a mocked request or response object, for example, outgoing API call.\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n### `headers`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Description\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eObject\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    A mapping of header names to header values. Case sensitive.\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n### `url`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Description\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eString\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    The full request URL.\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n\n### `method`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Description\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eString\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    The HTTP method such as \u003ccode\u003eGET\u003c/code\u003e or \u003ccode\u003ePOST\u003c/code\u003e.\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n### `statusCode`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Description\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eNumber\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    The HTTP response status code number.\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n### `getHeader`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Parameters\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Return type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Description\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    Function\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003e(String)\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eString\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    Reads out a header on the request. Name is case insensitive\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n### `get`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Parameters\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Return type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Description\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    Function\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003e(String)\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    \u003ccode\u003eString\u003c/code\u003e\n   \u003c/td\u003e\n   \u003ctd\u003e\n    Reads out a header on the request. Name is case insensitive\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n### `body`\n\u003ctable\u003e\n  \u003ctr\u003e\n   \u003cth scope=\"col\"\u003e\n    Data type\n   \u003c/th\u003e\n   \u003cth scope=\"col\"\u003e\n    Description\n   \u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n   \u003ctd\u003e\n    JSON object\n   \u003c/td\u003e\n   \u003ctd\u003e\n    The request body as sent to Moesif.\n   \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n## Koa Support\n\nSeveral of the Moesif [configuration options](#configuration-options) take a Node.js request ane response objects as arguments. You can access the Koa state object through `req.state`.\n\nAs an example, many Koa auth middleware save the authenticated user on `ctx.state.user`. You can access it through Moesif options like [`identifyUser`](#identifyuser):\n\n```javascript\n  identifyUser: function (req, res) {\n    if (req.state \u0026\u0026 req.state.user) {\n      return req.state.user.sub;\n    }\n    return undefined;\n  },\n```\n\n## Examples\n\n- [View example app with Express.js](https://github.com/Moesif/moesif-express-example).\n- [View example app with Koa](https://github.com/Moesif/moesif-koa-example).\n- [View example app with Apollo.js GraphQL.](https://github.com/Moesif/moesif-apollo-graphql-example)\n- [View example app with Express GraphQL.](https://github.com/Moesif/moesif-express-graphql-example)\n- [View example app with Next.js](https://github.com/Moesif/moesif-next-js-example)\n- [View example app with Fastify](https://github.com/Moesif/fastify-moesif-nodejs-example)\n- [View example app with Hapi](https://github.com/Moesif/moesif-nodejs-hapi-example)\n\nThe following examples demonstrate how to add and update customer information.\n\n### Update a Single User\nTo create or update a [user](https://www.moesif.com/docs/getting-started/users/) profile in Moesif, use the `updateUser()` function.\n\n```javascript\nvar moesifMiddleware = moesif(options);\n\n// Only userId is required.\n// Campaign object is optional, but useful if you want to track ROI of acquisition channels\n// See https://www.moesif.com/docs/api#users for campaign schema\n// metadata can be any custom object\nvar user = {\n  userId: '12345',\n  companyId: '67890', // If set, associate user with a company object\n  metadata: {\n    email: 'john@acmeinc.com',\n    firstName: 'John',\n    lastName: 'Doe',\n    title: 'Software Engineer',\n    salesInfo: {\n        stage: 'Customer',\n        lifetimeValue: 24000,\n        accountOwner: 'mary@contoso.com'\n    }\n  }\n};\n\nmoesifMiddleware.updateUser(user, callback);\n```\n\nThe `metadata` field can contain any customer demographic or other info you want to store. Moesif only requires the `userId` field.\n\nThis method is a convenient helper that calls the Moesif API library. For more information, see the function documentation in [Moesif Node.js API reference](https://www.moesif.com/docs/api?javascript--nodejs#update-a-user).\n\n### Update Users in Batch\nTo update a list of [users](https://www.moesif.com/docs/getting-started/users/) in one batch, use the `updateUsersBatch()` function.\n\n```javascript\nvar moesifMiddleware = moesif(options);\n\n// Only userId is required.\n// Campaign object is optional, but useful if you want to track ROI of acquisition channels\n// See https://www.moesif.com/docs/api#users for campaign schema\n// metadata can be any custom object\nvar user = {\n  userId: '12345',\n  companyId: '67890', // If set, associate user with a company object\n  metadata: {\n    email: 'john@acmeinc.com',\n    firstName: 'John',\n    lastName: 'Doe',\n    title: 'Software Engineer',\n    salesInfo: {\n        stage: 'Customer',\n        lifetimeValue: 24000,\n        accountOwner: 'mary@contoso.com'\n    }\n  }\n};\n\nvar users = [user]\n\nmoesifMiddleware.updateUsersBatch(users, callback);\n```\n\nThe `metadata` field can contain any customer demographic or other info you want to store. MOesif only requires the `userId` field.\n\nThis method is a convenient helper that calls the Moesif API library. For more information, see the function documentation in [Moesif Node.js API reference](https://www.moesif.com/docs/api?javascript--nodejs#update-users-in-batch).\n\n### Update a Single Company\nTo update a single [company](https://www.moesif.com/docs/getting-started/companies/), use the `updateCompany()` function.\n\n```javascript\nvar moesifMiddleware = moesif(options);\n\n// Only companyId is required.\n// Campaign object is optional, but useful if you want to track ROI of acquisition channels\n// See https://www.moesif.com/docs/api#update-a-company for campaign schema\n// metadata can be any custom object\nvar company = {\n  companyId: '67890',\n  companyDomain: 'acmeinc.com', // If domain is set, Moesif will enrich your profiles with publicly available info\n  metadata: {\n    orgName: 'Acme, Inc',\n    planName: 'Free Plan',\n    dealStage: 'Lead',\n    mrr: 24000,\n    demographics: {\n      alexaRanking: 500000,\n      employeeCount: 47\n    }\n  }\n};\n\nmoesifMiddleware.updateCompany(company, callback);\n```\n\nThe `metadata` field can contain any company demographic or other information you want to store. Moesif only requires the `companyId` field.\n\nThis method is a convenient helper that calls the Moesif API library. For more information, see the function documentation in [Moesif Node.js API reference](https://www.moesif.com/docs/api?javascript--nodejs#update-a-company).\n\n### Update Companies in Batch\nTo update a list of [companies](https://www.moesif.com/docs/getting-started/companies/) in one batch, use the `updateCompaniesBatch()` function.\n\n```javascript\nvar moesifMiddleware = moesif(options);\n\n// Only companyId is required.\n// Campaign object is optional, but useful if you want to track ROI of acquisition channels\n// See https://www.moesif.com/docs/api#update-a-company for campaign schema\n// metadata can be any custom object\nvar company = {\n  companyId: '67890',\n  companyDomain: 'acmeinc.com', // If domain is set, Moesif will enrich your profiles with publicly available info\n  metadata: {\n    orgName: 'Acme, Inc',\n    planName: 'Free Plan',\n    dealStage: 'Lead',\n    mrr: 24000,\n    demographics: {\n      alexaRanking: 500000,\n      employeeCount: 47\n    }\n  }\n};\n\nvar companies = [company]\n\nmoesifMiddleware.updateCompaniesBatch(companies, callback);\n```\n\nThe `metadata` field can contain any company demographic or other information you want to store. Moesif only requires the `companyId` field.\n\nThis method is a convenient helper that calls the Moesif API library. For more information, see the function documentation in [Moesif Node.js API reference](https://www.moesif.com/docs/api?javascript--nodejs#update-companies-in-batch).\n\n### Add a single Action\n\nTo track and log single [Action](https://www.moesif.com/docs/getting-started/user-actions/) in Moesif, use the `sendAction()` function.\n\n\n```javascript\nvar moesifMiddleware = moesif(options);\n\n// Only `actionName` and `request` is required.\n// `metadata` is an object containing custom metadata about the Action.\nvar action = {\n  transactionId: \"a3765025-46ec-45dd-bc83-b136c8d1d257\",\n  actionName: \"Clicked Sign Up\",\n  sessionToken: \"23jdf0owekfmcn4u3qypxg08w4d8ayrcdx8nu2nz]s98y18cx98q3yhwmnhcfx43f\",\n  userId: \"12345\",\n  companyId: \"67890\",\n  metadata: {\n    email: \"johndoe@acmeinc.com\",\n    button_label: 'Get Started',\n    sign_up_method: 'Google SSO'\n  },\n  request: {\n    time: new Date(),\n    uri: \"https://api.acmeinc.com/items/reviews/\",\n    ipAddress: \"61.48.220.123\",\n  }\n};\n// Send the Action\nmoesifMiddleware.sendAction(action, callback);\n```\n\nThe `metadata` field can contain any optional metadata about the Action you want to store. Moesif only requires the `actionName` and `request` fields.\n\nThis method is a convenient helper that calls the Moesif API library. For more information, see [Moesif API reference](https://www.moesif.com/docs/api?int_source=docs#track-a-custom-action).\n\n### Add a batch of Actions\n\nTo track and log a batch of [Actions](https://www.moesif.com/docs/getting-started/user-actions/) in Moesif, use the `sendActionsBatch()` function.\n\n\n```javascript\nvar moesifMiddleware = moesif(options);\n\n// Define the request context objects for each action.\nvar req_contextA = {\n  time: new Date(),\n  uri: \"https://api.acmeinc.com/items/reviews/\",\n  ipAddress: \"61.48.220.123\",\n  userAgentString: \"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0\"\n};\n\nvar req_contextB = {\n  time: new Date(),\n  uri: \"https://api.acmeinc.com/pricing/\",\n  ipAddress: \"61.48.220.126\",\n  userAgentString: \"PostmanRuntime/7.26.5\"\n};\n\n// Define the actions.\n// Only `actionName` and `request` is required.\n// `metadata` is an object containing custom metadata about the Action.\nvar actionA = {\n  transactionId: \"a3765025-46ec-45dd-bc83-b136a8d1d357\",\n  actionName: \"Clicked Sign Up\",\n  sessionToken: \"23abf0owekfmcn4u3qypxg09w4d8ayrcdx8nu2ng]s98y18cx98q3yhwmnhcfx43f\",\n  userId: \"18340\",\n  companyId: \"25100\",\n  metadata: {\n    email: \"alex@acmeinc.com\",\n    button_label: 'Get Started',\n    sign_up_method: 'Google SSO'\n  },\n  request: req_contextA\n};\n\nvar actionB = {\n  transactionId: \"a3765024-46ee-45dd-bc83-b136c8d1d250\",\n  actionName: \"Viewed pricing\",\n  sessionToken: \"23jdf0owejfmbn4u3qypxg09w4d8ayrxdx8nu2ng]s98y18cx98q3yhwmnhcfx43f\",\n  userId: \"12390\",\n  companyId: \"97895\",\n  metadata: {\n    email: \"kim@acmeinc.com\",\n    button_label: 'See pricing',\n    sign_up_method: 'Google SSO'\n  },\n  request: req_contextB\n};\n\nvar actions = [\n  actionA,\n  actionB\n];\n// Send the batch of Actions\nmoesifMiddleware.sendActionsBatch(actions, callback);\n```\n\nThe `metadata` field can contain any optional metadata about the Action you want to store. Moesif only requires the `actionName` and `request` fields.\n\nThis method is a convenient helper that calls the Moesif API library. For more information, see [Moesif API reference](https://www.moesif.com/docs/api?int_source=docs#track-custom-actions-in-batch).\n\n## How to Get Help\nIf you face any issues using this middleware, try the [troubheshooting guidelines](#troubleshoot). For further assistance, reach out to our [support team](mailto:support@moesif.com).\n\n## Explore Other Integrations\n\nExplore other integration options from Moesif:\n\n- [Server integration options documentation](https://www.moesif.com/docs/server-integration//)\n- [Client integration options documentation](https://www.moesif.com/docs/client-integration/)\n\n\n[ico-built-for]: https://img.shields.io/badge/built%20for-node.js-blue.svg\n[ico-downloads]: https://img.shields.io/npm/dt/moesif-nodejs.svg\n[ico-license]: https://img.shields.io/badge/License-Apache%202.0-green.svg\n[ico-source]: https://img.shields.io/github/last-commit/moesif/moesif-nodejs.svg?style=social\n\n[link-built-for]: https://expressjs.com/\n[link-downloads]: https://www.npmjs.com/package/moesif-nodejs\n[link-license]: https://raw.githubusercontent.com/Moesif/moesif-nodejs/master/LICENSE\n[link-source]: https://github.com/moesif/moesif-nodejs\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoesif%2Fmoesif-nodejs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmoesif%2Fmoesif-nodejs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoesif%2Fmoesif-nodejs/lists"}