{"info":{"_postman_id":"941aecfa-a192-46a6-98b0-756a76a4693f","name":"ProductMind - API","description":"<html><head></head><body><p>ProductMind is a powerful knowledge management platform that automates the conversion and organization of unstructured data from various sources like Google Drive, Notion, Github, and PDF documents into a searchable, centralized knowledge base. This API provides endpoints for file conversion, data synchronization, and interaction with the knowledge base, enabling seamless integration of ProductMind's capabilities into your workflow.</p>\n<h2 id=\"key-features\">Key features:</h2>\n<ul>\n<li><p><strong>Sync</strong>: Ingest and refresh data for a company</p>\n</li>\n<li><p><strong>Query</strong>: Query and explore the knowledge base</p>\n</li>\n<li><p><strong>Fetch</strong>: Get data out of 3rd party systems, such as Jira or SQL schemas</p>\n</li>\n<li><p><strong>Write</strong>: Write data to 3rd party systems, such as Notion</p>\n</li>\n<li><p><strong>Convert</strong>: Automated file conversion to Markdown format (used by Sync)</p>\n</li>\n</ul>\n</body></html>","schema":"https://schema.getpostman.com/json/collection/v2.0.0/collection.json","toc":[],"owner":"38070356","collectionId":"941aecfa-a192-46a6-98b0-756a76a4693f","publishedId":"2sAXqv4LMz","public":true,"customColor":{"top-bar":"FFFFFF","right-sidebar":"303030","highlight":"FF6C37"},"publishDate":"2024-09-24T14:09:01.000Z"},"item":[{"name":"Sync","item":[{"name":"Ingest data for a company","id":"eeece204-b133-4db1-aeea-d6a0ba1fc463","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"company\": \"quark_vendor_contracts\",\n  \"folders\": [\"https://drive.google.com/drive/folders/1z1yg3OIYSiSo06UqxjPWOfVFrdvSYg66?usp=sharing\"],\n  \"standalone\": true\n}","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/sync","description":"<p>This endpoint triggers the synchronization process for a specific company's data. It processes provided URLs (files and folders from various data sources).</p>\n<h3 id=\"parameters\">Parameters:</h3>\n<ul>\n<li><p><code>company_name</code> (string, required): The name of the company to synchronize data for.</p>\n</li>\n<li><p><code>files</code> (string[], optional): An array of URLs to process (see the Sync intro for supported data sources or file types).</p>\n</li>\n<li><p><code>folders</code> (string[], optional): An array of URLs to process. Alternative to <code>files</code>, list of urls will be combined from both parameters.</p>\n</li>\n<li><p><code>product</code> (string, optional): Set the product name.</p>\n</li>\n<li><p><code>type</code> (string, optional): Set the data type.</p>\n</li>\n<li><p><code>standalone</code> (boolean, optional): If set to true, the knowledge base synchronization will run after the sync is complete. Default is <code>true</code>. Useful to set to <code>false</code> during subsequent batched load, with running it as <code>true</code> for the last batch</p>\n</li>\n</ul>\n<blockquote>\n<p><strong>Note</strong>: either files or folders is required. </p>\n</blockquote>\n<p>All parameters should be passed in the request body as JSON.</p>\n<p>The response includes details on the results of the synchronization.</p>\n<blockquote>\n<p><strong>Note:</strong> This process may take some time depending on the amount of data to be synchronized.</p>\n</blockquote>\n","urlObject":{"protocol":"https","path":["sync"],"host":["productmind.trilogy.com"],"query":[],"variable":[]}},"response":[{"id":"08598959-6c53-417f-baea-5e2592b5ac0d","name":"Example Response","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"company\": \"quark_vendor_contracts\",\n  \"folders\": [\"https://drive.google.com/drive/folders/1z1yg3OIYSiSo06UqxjPWOfVFrdvSYg66?usp=sharing\"],\n  \"standalone\": true\n}","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/sync","description":"This endpoint triggers the synchronization process for a specific company's data. It processes provided URLs (files and folders from various data sources).\n\n### Parameters:\n\n- `company_name` (string, required): The name of the company to synchronize data for.\n    \n- `files` (string\\[\\], optional): An array of URLs to process (see the Sync intro for supported data sources or file types).\n    \n- `folders` (string\\[\\], optional): An array of URLs to process. Alternative to `files`, list of urls will be combined from both parameters.\n    \n- `product` (string, optional): Set the product name.\n    \n- `type` (string, optional): Set the data type.\n    \n- `standalone` (boolean, optional): If set to true, the knowledge base synchronization will run after the sync is complete. Default is `true`. Useful to set to `false` during subsequent batched load, with running it as `true` for the last batch\n    \n\n> **Note**: either files or folders is required. \n  \n\nAll parameters should be passed in the request body as JSON.\n\nThe response includes details on the results of the synchronization.\n\n> **Note:** This process may take some time depending on the amount of data to be synchronized."},"status":"OK","code":202,"_postman_previewlanguage":"text","header":[{"key":"Content-Type","value":"text/plain; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"Successfully synced 1 items (1 added, 0 modified, 0 renamed, 0 removed, 0 skipped) for company 'test-company-name'.\n            \nProduct details:\nProduct 'test-product-name' sync summary: 1 items (1 added, 0 modified, 0 skipped), 0 errors"}],"_postman_id":"eeece204-b133-4db1-aeea-d6a0ba1fc463"},{"name":"Remove data by URL","id":"43a06c39-d8f7-4e67-adf1-ddf4b10da0e0","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"url\": \"https://docs.google.com/spreadsheets/d/1ae5exvUJ-xgX_sEDejACjGQNfBMaQgGArJwdIKj12Lc/edit?usp=drive_link\"\n}\n","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/remove","description":"<p>Removes from the knowledge base a previously synced Url (file/page/etc.).</p>\n<h2 id=\"parameters\">Parameters</h2>\n<ul>\n<li><code>url</code> - the source file URL that should be removed (e.g. a Notion page link, or a Google drive file Url)</li>\n</ul>\n<p>See also: \"Remove data by company and filename\"</p>\n<h2 id=\"technical-details\">Technical details</h2>\n<ul>\n<li><p>the related database entry gets soft deleted</p>\n</li>\n<li><p>the source, markdown and metadata files get deleted in the S3 buckets</p>\n</li>\n</ul>\n","urlObject":{"protocol":"https","path":["remove"],"host":["productmind.trilogy.com"],"query":[],"variable":[]}},"response":[{"id":"05ce6e07-eeea-4fe1-ae4f-5d39922520fe","name":"Example Response","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"url\": \"https://docs.google.com/spreadsheets/d/1ae5exvUJ-xgX_sEDejACjGQNfBMaQgGArJwdIKj12Lc/edit?usp=drive_link\"\n}\n","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/remove","description":"Removes from the knowledge base a previously synced Url (file/page/etc.).\n\n## Parameters\n\n- `url` - the source file URL that should be removed (e.g. a Notion page link, or a Google drive file Url)\n    \n\nSee also: \"Remove data by company and filename\"\n\n## Technical details\n\n- the related database entry gets soft deleted\n    \n- the source, markdown and metadata files get deleted in the S3 buckets"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"Content removed successfully\",\n  \"url\": \"https://drive.google.com/drive/folders/1234567890abcdefghijklmnopqrstuvwxyz\",\n  \"company_id\": \"12345678-90ab-cdef-1234-567890abcdef\",\n  \"file_name\": \"test filename\"\n}"}],"_postman_id":"43a06c39-d8f7-4e67-adf1-ddf4b10da0e0"},{"name":"Remove data by company and filename","id":"32749ff2-8918-4623-9dc6-8b612decf1f0","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"company\": \"tsi\",\n  \"file_name\": \"Self-Serve Subscription Renewal Portal LAMBDA-79173\"\n}\n","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/remove","description":"<p>Removes from the knowledge base a previously synced Url (file/page/etc.).</p>\n<p>See also: \"Remove data by URL\"</p>\n<h2 id=\"parameters\">Parameters</h2>\n<ul>\n<li><p><code>company_name</code> - name of the company</p>\n</li>\n<li><p><code>file_name</code> - name of the file that should be removed (e.g. \"Product presentation.pdf\")</p>\n</li>\n</ul>\n<h2 id=\"technical-details\">Technical details</h2>\n<ul>\n<li><p>the related database entry gets soft deleted</p>\n</li>\n<li><p>the source, markdown and metadata files get deleted in the S3 buckets</p>\n</li>\n</ul>\n","urlObject":{"protocol":"https","path":["remove"],"host":["productmind.trilogy.com"],"query":[],"variable":[]}},"response":[{"id":"606cbfe1-d33e-4384-9baf-9f250c2a6075","name":"Example Response","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"company\": \"tsi\",\n  \"file_name\": \"Self-Serve Subscription Renewal Portal LAMBDA-79173\"\n}\n","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/remove","description":"Removes from the knowledge base a previously synced Url (file/page/etc.).\n\nSee also: \"Remove data by URL\"\n\n## Parameters\n\n- `company_name` - name of the company\n    \n- `file_name` - name of the file that should be removed (e.g. \"Product presentation.pdf\")\n    \n\n## Technical details\n\n- the related database entry gets soft deleted\n    \n- the source, markdown and metadata files get deleted in the S3 buckets"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"Content removed successfully\",\n  \"url\": \"https://drive.google.com/drive/folders/1234567890abcdefghijklmnopqrstuvwxyz\",\n  \"company_id\": \"12345678-90ab-cdef-1234-567890abcdef\",\n  \"file_name\": \"test filename\"\n}"}],"_postman_id":"32749ff2-8918-4623-9dc6-8b612decf1f0"},{"name":"Refresh data for a company","id":"db95cfc1-6672-4eed-a2ee-3cfbcb53cfa2","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"company\": \"test-company-name\",\n  \"product\": \"example-product\"\n}","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/sync","description":"<p>This endpoint triggers the synchronization process for a specific company's data. It retrieves known URLs from the database and refreshes all changed ones and adds new files/subpages from known folders.</p>\n<h3 id=\"parameters\">Parameters:</h3>\n<ul>\n<li><p><code>company_name</code> (string, required): The name of the company to synchronize data for.</p>\n</li>\n<li><p><code>product</code> (string, optional): Limit the refresh to a specific product.</p>\n</li>\n<li><p><code>type</code> (string, optional): Limit the refresh to a specific data type.</p>\n</li>\n<li><p><code>standalone</code> (boolean, optional): If set to true, the knowledge base synchronization will run after the sync is complete. Default is <code>true</code>.</p>\n</li>\n</ul>\n<p>All parameters should be passed in the request body as JSON.</p>\n<p>The response includes details on the results of the synchronization.</p>\n<blockquote>\n<p><strong>Note:</strong> This process may take some time depending on the amount of data to be synchronized.</p>\n</blockquote>\n","urlObject":{"protocol":"https","path":["sync"],"host":["productmind.trilogy.com"],"query":[],"variable":[]}},"response":[{"id":"1d2f53b3-8994-48aa-b7a7-7953ff007751","name":"Example Response","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"company\": \"test-company-name\",\n  \"product\": \"example-product\"\n}","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/sync","description":"This endpoint triggers the synchronization process for a specific company's data. It retrieves known URLs from the database and refreshes all changed ones and adds new files/subpages from known folders.\n\n### Parameters:\n\n- `company_name` (string, required): The name of the company to synchronize data for.\n    \n- `product` (string, optional): Limit the refresh to a specific product.\n    \n- `type` (string, optional): Limit the refresh to a specific data type.\n    \n- `standalone` (boolean, optional): If set to true, the knowledge base synchronization will run after the sync is complete. Default is `true`.\n    \n\nAll parameters should be passed in the request body as JSON.\n\nThe response includes details on the results of the synchronization.\n\n> **Note:** This process may take some time depending on the amount of data to be synchronized."},"status":"OK","code":202,"_postman_previewlanguage":"text","header":[{"key":"Content-Type","value":"text/plain; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"Successfully synced 1 items (1 added, 0 modified, 0 renamed, 0 removed, 0 skipped) for company 'test-company-name'.\n            \nProduct details:\nProduct 'test-product-name' sync summary: 1 items (1 added, 0 modified, 0 skipped), 0 errors"}],"_postman_id":"db95cfc1-6672-4eed-a2ee-3cfbcb53cfa2"}],"id":"952cfc68-2912-46c9-9204-e96e829ad414","description":"<p>The Sync folder contains endpoints for <strong>ingesting and refreshing data</strong> for a specific company within ProductMind. These endpoints handle the synchronization of data from various sources, including Google Drive (Docs, Sheets, PDFs, txt), Notion, Github (Markdown, txt, YAML), and Postman Documentation into the knowledge base. They support both initial data ingestion and ongoing updates, ensuring that the ProductMind repository always reflects the most current information from your connected data sources.</p>\n","_postman_id":"952cfc68-2912-46c9-9204-e96e829ad414"},{"name":"Query","item":[{"name":"List companies","id":"3dc78b04-7668-45da-b045-691f91f5c413","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"command\": \"list_companies\"\n}\n","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/list","description":"<p>This endpoint retrieves a list of companies stored in the ProductMind knowledge base.</p>\n<h3 id=\"parameters\">Parameters:</h3>\n<ul>\n<li><code>command</code> (string, required): `list_companies'</li>\n</ul>\n<p>All parameters should be passed in the request body as JSON.</p>\n","urlObject":{"protocol":"https","path":["list"],"host":["productmind.trilogy.com"],"query":[],"variable":[]}},"response":[{"id":"7d90cfcc-ada7-435d-94cf-1cc2ed6f836f","name":"Example Response","originalRequest":{"header":[]},"status":"OK","code":200,"_postman_previewlanguage":"text","header":[{"key":"Content-Type","value":"text/plain; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"* act-on\n* centreviews\n* cirrus_insight\n* cloudhouse\n* cognitoforms\n* contently\n..."}],"_postman_id":"3dc78b04-7668-45da-b045-691f91f5c413"},{"name":"List files of a company","id":"2b154e98-bf9f-4f9c-96f6-c4322943eef0","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"command\": \"list_files\",\n    \"company\": \"test-product-name\"\n}\n","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/list","description":"<p>This endpoint retrieves a list of all files and folders currently stored in the ProductMind knowledge base for a specific company.</p>\n<h3 id=\"parameters\">Parameters:</h3>\n<ul>\n<li><code>command</code> (string, required): `list_files'</li>\n<li><code>company</code> (string, required): The name of the company to list files for.</li>\n</ul>\n<p>All parameters should be passed in the request body as JSON.</p>\n","urlObject":{"protocol":"https","path":["list"],"host":["productmind.trilogy.com"],"query":[],"variable":[]}},"response":[{"id":"492e92dc-cf21-4328-b621-621db7a1784f","name":"Example Response","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"command\": \"list_files\",\n    \"company\": \"test-product-name\"\n}\n","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/list","description":"This endpoint retrieves a list of all files and folders currently stored in the ProductMind knowledge base for a specific company.\n\n### Parameters:\n- `command` (string, required): `list_files'\n- `company` (string, required): The name of the company to list files for.\n\nAll parameters should be passed in the request body as JSON."},"status":"OK","code":200,"_postman_previewlanguage":"text","header":[{"key":"Content-Type","value":"text/plain; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"# test-company-name\n* Notion Page\n  * [2a.1.iii - another nested test page](https://www.notion.so/2a1iii--another-nested-test-page-36948b7cd32f41e69e204abea3e74693)\n  * [2b.1 - Test page for]\n  ...\n...\n            "}],"_postman_id":"2b154e98-bf9f-4f9c-96f6-c4322943eef0"},{"name":"Query the knowledge base","id":"436ae6d9-6f35-4d66-8188-ad65f41624a5","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\"query\":\"pricing\",\"company\":\"tivian\",\"output\":\"chunks\",\"results\":3}","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/query","description":"<p>This endpoint allows querying the ProductMind knowledge base. It provides powerful search capabilities across all converted and organized content.</p>\n<h3 id=\"parameters\">Parameters:</h3>\n<ul>\n<li><p><code>query</code> (string, required): The search query string.</p>\n</li>\n<li><p><code>company</code> (string, required): The company name for which to search.</p>\n</li>\n<li><p><code>product</code> (string, optional): Filter results by product name.</p>\n</li>\n<li><p><code>type</code> (string, optional): Filter results by data type</p>\n</li>\n<li><p><code>refresh</code> (boolean, optional): Whether to refresh the search index before querying. Default is false.</p>\n</li>\n<li><p><code>output</code> (string, optional): What to return, full \"docs\" (default) or \"chunks\"</p>\n</li>\n<li><p><code>return_type</code> (string, optional): Default to 'document'</p>\n</li>\n<li><p><code>results</code> (number, optional): Maximum number of results to return. Default is 10.</p>\n</li>\n</ul>\n<p>All parameters should be passed in the request body as JSON.</p>\n","urlObject":{"protocol":"https","path":["query"],"host":["productmind.trilogy.com"],"query":[],"variable":[]}},"response":[{"id":"0a8b8304-92c1-41e4-aaf2-9b8fef069dba","name":"Example Response","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\"query\":\"pricing\",\"company\":\"tivian\",\"output\":\"chunks\",\"results\":3}","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/query","description":"This endpoint allows querying the ProductMind knowledge base. It provides powerful search capabilities across all converted and organized content.\n\n### Parameters:\n\n- `query` (string, required): The search query string.\n    \n- `company` (string, required): The company name for which to search.\n    \n- `product` (string, optional): Filter results by product name.\n    \n- `type` (string, optional): Filter results by data type\n    \n- `refresh` (boolean, optional): Whether to refresh the search index before querying. Default is false.\n    \n- `output` (string, optional): What to return, full \"docs\" (default) or \"chunks\"\n    \n- `return_type` (string, optional): Default to 'document'\n    \n- `results` (number, optional): Maximum number of results to return. Default is 10.\n    \n\nAll parameters should be passed in the request body as JSON."},"status":"OK","code":200,"_postman_previewlanguage":"text","header":[{"key":"Content-Type","value":"text/plain; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"<documents>\n  <document index=\"1\">\n    <source>test-company-name/example-product/L2/Platform APIs.md</source>\n    <url>https://ws-eng.postman.co/workspace/Platform-Prod~66ec436e-5fcd-43ad-964c-f70d5ca1225f/collection/31124709-d038145a-a2fd-46f9-8cd1-f6024afbbf72</url>\n    <document_content>\n      <![CDATA[\n</qti-prompt>\\n      <qti-simple-choice identifier=\\\"A\\\">It induced a rise in global alliances and partnerships.</qti-simple-choice>\\n      <qti-simple-choice identifier=\\\"B\\\">It heightened political tensions between East and West.</qti-simple-choice>\\n      <qti-simple-choice identifier=\\\"C\\\">It increased isolation and societal division.</qti-simple-choice>\\n      <qti-simple-choice identifier=\\\"D\\\">It led to the decline of the English Language.</qti-simple-choice>\\n    </qti-choice-interaction>\\n    <qti-media-interaction response-identifier=\\\"HELP_REQUESTED\\\" autostart=\\\"false\\\">\\n      <video controls=\\\"true\\\" data-speaker-name=\\\"John F. Kennedy\\\" data-speaker-biography-short=\\\"35th US President\\\" data-speaker-image=\\\"https://alphacoachbot-production-midjourney-images.s3.us-east-1.amazonaws.com/production/mcq6speakerImage.jpg\\\">\\nHere&apos;s what you need to know: The subdued rivalry of imperialism in the 20th century paved the way for an integrated and globalized world. With a decrease in imperialistic competition, countries had room to increase global partnerships spanning different sectors like economies, cultures, and politics.        <source src=\\\"https://alphacoachbot-production-midjourney-images.s3.us-east-1.amazonaws.com/production/mcq6Video.mp4\\\" type=\\\"video/mp4\\\"/>\\n      </video>\\n    </qti-media-interaction>\\n  </qti-item-body>\\n  <qti-response-processing template=\\\"https://purl.imsglobal.org/spec/qti/v3p0/rptemplates/match_correct\\\"/>\\n</qti-assessment-item>\\n\",\n\"clusterId\": \"AP World Topic 9.6\",\n\"clusterDescription\": \"Globalized Culture After 1900\",\n\"attributes\": []\n}\n]\n}\n}\n```\n⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃\n## End-point: getDMChatHistory\nThis endpoint allows to get chat history that student made with a key figure. Uses pagination with 50 item per page.\n## Input\ninput object with below parameters:\n- `keyFigureName` (string, required) Name of the key figure. `getHistoricalFigures` query can be used to retrieve key figure names.\n- `generatedContentId` (string) Content ID if you want to retrieve chat history for specific content.\n- `page` (integer) Page number to retrieve, starts from zero.\n## Output\nThe output is an object with the following attributes:\n- `hasNextPage` (boolean): Indicates if there is next page to retrieve.\n- `chatHistory` (list): Contains list of object with following fields\n- `message` (string): Message content\n- `senderUserId` (string): The user ID of the sender\n- `timestamp` (string): The iso formatted timestamp of message sent\n- `platformGeneratedContentID` (string): generatedContentId if conversation belongs to specific content\n### Method: POST\n>```\n>{{GRAPHQL_URL}}\n>```\n### Headers\n      ]]>\n    </document_content>\n  </document>\n  <document index=\"2\">\n    <source>test-company-name/example-product/Copy of Features summary.md</source>\n    <url>https://drive.google.com/file/d/1k_TEXdtY6eR7QADDuti86audfwRwKxm58u7BTj01pJU/view?usp=sharing</url>\n    <document_content>\n      <![CDATA[\n# Copy of Features summary\n## Sheet1\n| Feature | Description |\n| - | - |\n| Coolness | The product is really cool |\n\n      ]]>\n    </document_content>\n  </document>\n  <document index=\"3\">\n    <source>test-company-name/example-product/Features summary.md</source>\n    <url>https://drive.google.com/file/d/1VPtcMjO5x_JjS0btYKxJMM_tHcVO3ryo_BfPKO26jPU/view?usp=sharing</url>\n    <document_content>\n      <![CDATA[\n# Features summary\n## Sheet1\n| Feature | Description |\n| - | - |\n| Coolness | The product is really cool |\n\n      ]]>\n    </document_content>\n  </document>\n  <document index=\"4\">\n    <source>test-company-name/example-product/Copy of Cool Feature description.md</source>\n    <url>https://drive.google.com/file/d/1jP80-UcTfiUkt2NIr4MYWBxQ18EqgVAeTx3wxRxWN-4/view?usp=sharing</url>\n    <document_content>\n      <![CDATA[\n# Cool Feature description\nLorem ipsum….\n      ]]>\n    </document_content>\n  </document>\n  <document index=\"5\">\n    <source>test-company-name/example-product/Cool Feature description.md</source>\n    <url>https://drive.google.com/file/d/1A3oxDcaolfIHINCuQZA9EkZ31_8KJT2WeXWUX0z8tbA/view?usp=sharing</url>\n    <document_content>\n      <![CDATA[\n# Cool Feature description\nLorem ipsum….\n      ]]>\n    </document_content>\n  </document>\n</documents>\n            "}],"_postman_id":"436ae6d9-6f35-4d66-8188-ad65f41624a5"}],"id":"b86b8070-d4d8-44b4-9361-c47d3e2256b2","description":"<p>The Query endpoints provide powerful <strong>search and retrieval capabilities</strong> for the ProductMind knowledge base. These endpoints allow you to search across the centralized repository of converted and organized content, making it easy to find specific information, explore relationships between different pieces of content, and leverage the full value of your knowledge base for decision-making and information retrieval.</p>\n","_postman_id":"b86b8070-d4d8-44b4-9361-c47d3e2256b2"},{"name":"Fetch","item":[{"name":"Fetch Jira tickets","id":"9f2c320c-4ca7-4a04-a8af-5c9f42f53d2d","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"tickets\": [\"TAI-34\", \"TAI-36\"]\n}","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/fetch/jira-tickets","description":"<p>This endpoint retrieves Jira tickets based on the provided query parameters. It allows users to fetch ticket information from Jira and returns the data in a structured format.</p>\n<h3 id=\"parameters\">Parameters:</h3>\n<ul>\n<li><code>tickets</code> (string[], required): List of Jira ticket IDs to fetch.</li>\n<li><code>export_sub_tasks</code> (boolean, optional): Controls whether to include also subtasks. Default is true.</li>\n</ul>\n<p>All parameters should be passed in the request body as JSON.</p>\n","urlObject":{"protocol":"https","path":["fetch","jira-tickets"],"host":["productmind.trilogy.com"],"query":[],"variable":[]}},"response":[{"id":"2cd6aed1-2f97-4c87-92ae-0970f5bc905b","name":"Example Response","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"tickets\": [\"TAI-34\", \"TAI-36\"]\n}","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/fetch/jira-tickets","description":"This endpoint retrieves Jira tickets based on the provided query parameters. It allows users to fetch ticket information from Jira and returns the data in a structured format.\n\n### Parameters:\n- `tickets` (string[], required): List of Jira ticket IDs to fetch.\n- `export_sub_tasks` (boolean, optional): Controls whether to include also subtasks. Default is true.\n\nAll parameters should be passed in the request body as JSON."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json","enabled":true}],"cookie":[],"responseTime":null,"body":"[\n  {\n    \"key\": \"TAI-34\",\n    \"summary\": \"Create friendly names for all of our APIs\",\n    \"product\": \"Trilogy: Gen AI - ProductMind\",\n    \"description\": \"The base domain should be \\\\*.productmind.trilogy.com\\n\\n...\",\n    \"output\": \"# CHANGELOG...\"\n  },\n  {\n    \"key\": \"TAI-36\",\n    \"summary\": \"Add support for importing API documentation from Postman\",\n    \"product\": \"Trilogy: Gen AI - ProductMind\",\n    \"description\": \"...\",\n    \"output\": \"# CHANGELOG...\"\n  }\n]"}],"_postman_id":"9f2c320c-4ca7-4a04-a8af-5c9f42f53d2d"},{"name":"Fetch SQL Schema","id":"4cc5a08e-ff5b-4a4a-b304-bc9749328fff","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"user\": \"db_user\",\n    \"password\": \"secure_password\",\n    \"hostname\": \"db.hostname.com\",\n    \"database\": \"sample_database\",\n    \"tables\": [\"table1\", \"table2\", \"table3\"],\n    \"modules\": [\"module1\", \"module2\"],\n    \"skip_cleanup\": true\n}\n","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/fetch/sql-schema","description":"<p>This endpoint retrieves the SQL schema for a specified database. It allows users to fetch table structures, column definitions, and relationships, providing a comprehensive view of the database schema.</p>\n<h3 id=\"parameters\">Parameters:</h3>\n<ul>\n<li><code>user</code> (string, required): The username for database authentication.</li>\n<li><code>password</code> (string, required): The password for database authentication.</li>\n<li><code>hostname</code> (string, required): The hostname of the database server.</li>\n<li><code>database</code> (string, required): The name or identifier of the database for which to fetch the schema.</li>\n<li><code>tables</code> (string[], optional): An array of specific table names to fetch. If not provided, the schema for all tables will be returned.</li>\n<li><code>modules</code> (string[], optional): An array of specific modules to include in the schema.</li>\n<li><code>skip_cleanup</code> (boolean, optional): Whether to skip cleanup operations after fetching the schema. Default is false.</li>\n</ul>\n<p>All parameters should be passed in the request body as JSON.</p>\n","urlObject":{"protocol":"https","path":["fetch","sql-schema"],"host":["productmind.trilogy.com"],"query":[],"variable":[]}},"response":[{"id":"1a8a934a-2415-4ce2-9021-1b2b2a8168eb","name":"Example Response","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"user\": \"db_user\",\n    \"password\": \"secure_password\",\n    \"hostname\": \"db.hostname.com\",\n    \"database\": \"sample_database\",\n    \"tables\": [\"table1\", \"table2\", \"table3\"],\n    \"modules\": [\"module1\", \"module2\"],\n    \"skip_cleanup\": true\n}\n","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/fetch/sql-schema","description":"This endpoint retrieves the SQL schema for a specified database. It allows users to fetch table structures, column definitions, and relationships, providing a comprehensive view of the database schema.\n\n### Parameters:\n- `user` (string, required): The username for database authentication.\n- `password` (string, required): The password for database authentication.\n- `hostname` (string, required): The hostname of the database server.\n- `database` (string, required): The name or identifier of the database for which to fetch the schema.\n- `tables` (string[], optional): An array of specific table names to fetch. If not provided, the schema for all tables will be returned.\n- `modules` (string[], optional): An array of specific modules to include in the schema.\n- `skip_cleanup` (boolean, optional): Whether to skip cleanup operations after fetching the schema. Default is false.\n\nAll parameters should be passed in the request body as JSON."},"status":"OK","code":200,"_postman_previewlanguage":"text","header":[{"key":"Content-Type","value":"text/plain; charset=UTF-8","enabled":true}],"cookie":[],"responseTime":null,"body":"# TABLE grades - Models grades academic courses are taught in. <module=skill_stack><module=curriculum>\nCREATE TABLE grades (\nid char(36) NOT NULL DEFAULT (uuid()) COMMENT 'uuid',\ngrade enum('PK','K','1','2','3','4','5','6','7','8','9','10','11','12','AP') NOT NULL COMMENT 'Grade that can be associated with the academic course.',\nname varchar(255) NOT NULL COMMENT 'Display name for the grade, e.g. Level 100 for 1st Grade.',"}],"_postman_id":"4cc5a08e-ff5b-4a4a-b304-bc9749328fff"},{"name":"Download source file","id":"a041c703-8830-48df-9759-6c36d1089b52","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"url\": \"https://drive.google.com/file/d/1U7iDkCEjhlk0fzDuy-l-GB1BJb0c20EC/view?usp=drive_link\"\n}\n","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/fetch/source","description":"<h3 id=\"fetch-source\">Fetch Source</h3>\n<p>This endpoint allows you to download the original source files from any of the supported data sources.</p>\n<h4 id=\"request-body\">Request Body</h4>\n<ul>\n<li><p><code>url</code> (text): The URL of the resource to be fetched.</p>\n</li>\n<li><p><code>return_mode</code> (enum): Controlling how the results are returned. Possible options:</p>\n<ul>\n<li><p><code>auto</code> / <code>direct</code> (Default): Will redirect to the file, so you will receive the binary content with the proper mime_type set</p>\n</li>\n<li><p><code>s3_url</code>: Will return an S3 presigned url (valid for 1h) and the mime type of the content as a JSON object</p>\n</li>\n</ul>\n</li>\n</ul>\n<h4 id=\"response\">Response</h4>\n<p>By default (`auto` and <code>direct</code> return mode) the result will be a redirect to the binary content (which clients usually automatically follow, so effectively the result is binary content).</p>\n<p>Using the <code>s3_url</code> return option the response is in JSON format and includes the following fields:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{\n  \"downloadUrl\": \"\",\n  \"contentType\": \"\"\n}\n\n</code></pre>\n<ul>\n<li><p><code>downloadUrl</code> (string): The S3 presigned URL for downloading the fetched resource.</p>\n</li>\n<li><p><code>contentType</code> (string): The content type of the fetched resource.</p>\n</li>\n</ul>\n","urlObject":{"protocol":"https","path":["fetch","source"],"host":["productmind.trilogy.com"],"query":[],"variable":[]}},"response":[{"id":"b979f3b6-185b-4cb7-a5dd-3143d9cb6442","name":"Download source file as binary","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"url\": \"https://drive.google.com/file/d/1U7iDkCEjhlk0fzDuy-l-GB1BJb0c20EC/view?usp=drive_link\"\n}\n","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/fetch/source"},"_postman_previewlanguage":null,"header":null,"cookie":[],"responseTime":null,"body":null},{"id":"15a3829e-ce51-45b1-8ac2-9f12ee75616f","name":"Download source file as S3 url","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"url\": \"https://drive.google.com/file/d/1U7iDkCEjhlk0fzDuy-l-GB1BJb0c20EC/view?usp=drive_link\",\n    \"return_mode\": \"s3_url\"\n}\n","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/fetch/source"},"_postman_previewlanguage":null,"header":null,"cookie":[],"responseTime":null,"body":null}],"_postman_id":"a041c703-8830-48df-9759-6c36d1089b52"}],"id":"6338de53-12da-4282-a9de-4e28d4268a8c","description":"<p>The Fetch endpoints allow you to retrieve data from external systems. These endpoints facilitate the extraction of information from third-party tools like Jira for project management data or SQL databases for schema information.</p>\n","_postman_id":"6338de53-12da-4282-a9de-4e28d4268a8c"},{"name":"Write","item":[{"name":"Create a Notion page from Markdown content","id":"ebc4930d-3031-40f9-98a6-8585c4ae9c8a","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"command\": \"create\",\n  \"parent_page_id\": \"https://www.notion.so/trilogy-enterprises/test-page-14d85e927d3180d19dfadc3c5b7758d7\",\n  \"content\": \"# New Page\\n\\nThis is a new page created via the API.\\nWith some bullets:\\n- bullet 1\\n- bullet 2\\n- bullet 3\",\n  \"title\": \"API Created Page\"\n}","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/write/notion","description":"<p>This endpoint allows writing content to Notion pages, creating a new page.</p>\n<h3 id=\"parameters\">Parameters:</h3>\n<ul>\n<li><p><code>command</code> (string, required): The operation to perform. Should be \"create\".</p>\n</li>\n<li><p><code>parent_page_id</code> (string, required): The ID of the parent page when creating a new page.</p>\n</li>\n<li><p><code>content</code> (string, required): The Markdown content to be written to the page.</p>\n</li>\n<li><p><code>title</code> (string, optional): The title for the newly created page. If missing it will be generated from the content automatically.</p>\n</li>\n</ul>\n<p>All parameters should be passed in the request body as JSON.</p>\n","urlObject":{"protocol":"https","path":["write","notion"],"host":["productmind.trilogy.com"],"query":[],"variable":[]}},"response":[{"id":"8129d127-a6ef-4aa2-8a7f-fafd4644c452","name":"Example Response","originalRequest":{"header":[]},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"page_id\": \"0987654321fedcba0987654321fedcba\",\n  \"page_url\": \"https://www.notion.so/My-New-Page-0987654321fedcba0987654321fedcba\"\n}"}],"_postman_id":"ebc4930d-3031-40f9-98a6-8585c4ae9c8a"},{"name":"Append Markdown content to a Notion page","id":"05689626-7b7b-4559-acd6-6f0b6c975730","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"command\": \"append\",\n  \"page_id\": \"3307018d-d8c2-43e4-9419-4c28b0c16678\",\n  \"content\": \"Adding some more content to this page.\\nLet's try a numbered list:\\n1. First item\\n2. Second item\\n3. Third item\"\n}","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/write/notion","description":"<p>This endpoint allows writing content to Notion pages, appending content to an existing page.</p>\n<h3 id=\"parameters\">Parameters:</h3>\n<ul>\n<li><p><code>command</code> (string, required): The operation to perform. Should be \"append\".</p>\n</li>\n<li><p><code>page_id</code> (string, required): The ID of the target Notion page.</p>\n</li>\n<li><p><code>content</code> (string, required): The Markdown content to be added to the page.</p>\n</li>\n<li><p><code>title</code> (string, optional): The title to replace the existing page title. When skipped the title is not changed.</p>\n</li>\n</ul>\n<p>All parameters should be passed in the request body as JSON.</p>\n","urlObject":{"protocol":"https","path":["write","notion"],"host":["productmind.trilogy.com"],"query":[],"variable":[]}},"response":[{"id":"3b8c44f0-72c3-471c-b882-52cc0902e679","name":"Example Response","originalRequest":{"header":[]},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"page_id\": \"0987654321fedcba0987654321fedcba\",\n  \"page_url\": \"https://www.notion.so/My-New-Page-0987654321fedcba0987654321fedcba\"\n}"}],"_postman_id":"05689626-7b7b-4559-acd6-6f0b6c975730"},{"name":"Replace content of a Notion Page from Markdown","id":"e1f80aad-d6d9-4278-b37a-2510062392a7","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"command\": \"replace\",\n  \"page_id\": \"3307018dd8c243e494194c28b0c16678\",\n  \"content\": \"# This is an updated Page\\n\\nThis is a page with content replaced via the API.\\n\\nWith some bullets:\\n- bullet 1\\n- bullet 2\\n- bullet 3\",\n  \"title\": \"API Created Page with a changed title\"\n}","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/write/notion","description":"<p>This endpoint allows writing content to Notion pages, replacing the content of an existing page.</p>\n<h3 id=\"parameters\">Parameters:</h3>\n<ul>\n<li><p><code>command</code> (string, required): The operation to perform. Should be \"replace\".</p>\n</li>\n<li><p><code>page_id</code> (string, required): The ID of the target Notion page.</p>\n</li>\n<li><p><code>content</code> (string, required): The Markdown content to be written to the page.</p>\n</li>\n<li><p><code>title</code> (string, optional): The title to replace the existing page title. When skipped the title is not changed.</p>\n</li>\n</ul>\n<p>All parameters should be passed in the request body as JSON.</p>\n<blockquote>\n<p>Note: this operation is slow because of technical details of the Notion API. Creating a new page or appending to an existing is much more preferred.</p>\n</blockquote>\n","urlObject":{"protocol":"https","path":["write","notion"],"host":["productmind.trilogy.com"],"query":[],"variable":[]}},"response":[{"id":"8aa02f9e-2feb-4a35-9905-8af9d4893182","name":"Example Response","originalRequest":{"header":[]},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"page_id\": \"0987654321fedcba0987654321fedcba\",\n  \"page_url\": \"https://www.notion.so/My-New-Page-0987654321fedcba0987654321fedcba\"\n}"}],"_postman_id":"e1f80aad-d6d9-4278-b37a-2510062392a7"},{"name":"Replace (recreate) a Notion Page from Markdown","id":"964d59b6-b840-48e3-8267-d0e41865ca70","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"command\": \"replace_page\",\n  \"page_id\": \"3307018dd8c243e494194c28b0c16678\",\n  \"content\": \"# This is an updated Page\\n\\nThis is a page with content replaced via the API.\\n\\nWith some bullets:\\n- bullet 1\\n- bullet 2\\n- bullet 3\",\n  \"title\": \"API Created Page with a changed title\"\n}","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/write/notion","description":"<p>This endpoint allows writing content to Notion pages, replacing an existing page by first deleting it and then recreating it.</p>\n<p>This option is significantly faster than regular \"replace\", but it results in the ID and URL of the page changing. If that's acceptable we recommend using this option.</p>\n<h3 id=\"parameters\">Parameters:</h3>\n<ul>\n<li><p><code>command</code> (string, required): The operation to perform. Should be \"replace_page\".</p>\n</li>\n<li><p><code>page_id</code> (string, required): The ID of the target Notion page.</p>\n</li>\n<li><p><code>content</code> (string, required): The Markdown content to be written to the page.</p>\n</li>\n<li><p><code>title</code> (string, optional): The title to replace the existing page title. When skipped the title is not changed.</p>\n</li>\n</ul>\n<p>All parameters should be passed in the request body as JSON.</p>\n<blockquote>\n<p>Note: the parent page needs to be shared with the ProductMind integration, so it will be able to create the new page.</p>\n</blockquote>\n","urlObject":{"protocol":"https","path":["write","notion"],"host":["productmind.trilogy.com"],"query":[],"variable":[]}},"response":[{"id":"c481f40e-5c8d-4a43-99a2-9cd4d5bc61b0","name":"Example Response","originalRequest":{"header":[]},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"page_id\": \"0987654321fedcba0987654321fedcba\",\n  \"page_url\": \"https://www.notion.so/My-New-Page-0987654321fedcba0987654321fedcba\"\n}"}],"_postman_id":"964d59b6-b840-48e3-8267-d0e41865ca70"},{"name":"Create a Google sheet from CSV content","id":"d33ed543-ab1b-426a-9373-0b58d7ef3144","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"gdrive_folder_url\": \"https://drive.google.com/drive/folders/1GyazgZsdsjDx9bqy2hMOeDE8yjH25I_C?usp=sharing\",\n  \"filename\": \"Test CSV Sheet\",\n  \"csv_content\": \"header1,header2,header3\\nvalue1,value2,value3\\nvalue4,value5,value6\"\n} ","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/write/gsheet","description":"<h3 id=\"write-to-google-sheet\">Write to Google Sheet</h3>\n<p>The endpoint allows you to write CSV data to a new Google Sheet.</p>\n<h4 id=\"request-body\">Request Body</h4>\n<ul>\n<li><p><code>gdrive_folder_url</code> (string): The URL of the Google Drive folder where the sheet will be saved.</p>\n</li>\n<li><p><code>filename</code> (string): The name of the CSV sheet file.</p>\n</li>\n<li><p><code>csv_content</code> (string): The content of the CSV sheet in the format \"header1,header2,header3\\nvalue1...\"</p>\n</li>\n</ul>\n<h4 id=\"response\">Response</h4>\n<p>The response is in JSON format with the following schema:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{\n  \"sheet_url\": \"\"\n}\n\n</code></pre>\n<ul>\n<li><code>sheet_url</code> (string): The URL of the created Google Sheet.</li>\n</ul>\n","urlObject":{"protocol":"https","path":["write","gsheet"],"host":["productmind.trilogy.com"],"query":[],"variable":[]}},"response":[{"id":"afc9b6f2-ce60-4cc4-a2f9-79df24e9c64a","name":"Example request","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"gdrive_folder_url\": \"https://drive.google.com/drive/folders/1GyazgZsdsjDx9bqy2hMOeDE8yjH25I_C?usp=sharing\",\n  \"filename\": \"Test CSV Sheet\",\n  \"csv_content\": \"header1,header2,header3\\nvalue1,value2,value3\\nvalue4,value5,value6\"\n} ","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/write/gsheet"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Date","value":"Fri, 28 Mar 2025 09:16:32 GMT"},{"key":"Content-Type","value":"application/json"},{"key":"Content-Length","value":"100"},{"key":"Connection","value":"keep-alive"},{"key":"x-amzn-RequestId","value":"ca8c5e8d-7917-46ab-8ca5-63ad56d82505"},{"key":"x-amz-apigw-id","value":"IIVU3HAwoAMEgtg="},{"key":"X-Amzn-Trace-Id","value":"Root=1-67e668eb-0e0315e916f0ecd65c82b02c;Sampled=1;Lineage=1:0a137e45:0"}],"cookie":[],"responseTime":null,"body":"{\n    \"sheet_url\": \"https://docs.google.com/spreadsheets/d/1LP6K41EKo0OrbcElLbHYolfzzkX4zp71Mqcua_ys7_I\"\n}"}],"_postman_id":"d33ed543-ab1b-426a-9373-0b58d7ef3144"},{"name":"Create a Google doc from Markdown content","id":"a4836394-904a-49da-918f-9d33e43eab7e","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"gdrive_folder_url\": \"https://drive.google.com/drive/folders/1GyazgZsdsjDx9bqy2hMOeDE8yjH25I_C?usp=sharing\",\n  \"filename\": \"Test Markdown Document\",\n  \"markdown_content\": \"# Test Heading\\n\\nThis is a test markdown document.\\n\\n## Subheading\\n\\n- List item 1\\n- List item 2\\n\\n**Bold text** and *italic text*.\"\n} ","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/write/gdoc","description":"<h3 id=\"write-to-google-document\">Write to Google Document</h3>\n<p>This endpoint allows you to write Markdown content to a new Google Document.</p>\n<h4 id=\"request-body\">Request Body</h4>\n<ul>\n<li><p><code>gdrive_folder_url</code> (string): The URL of the Google Drive folder where the document will be saved.</p>\n</li>\n<li><p><code>filename</code> (string): The name of the document file.</p>\n</li>\n<li><p><code>markdown_content</code> (string): The content of the document in markdown format.</p>\n</li>\n</ul>\n<h4 id=\"response\">Response</h4>\n<p>The response is in JSON format with the following schema:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{\n  \"doc_url\": \"\"\n}\n\n</code></pre>\n<ul>\n<li><code>doc_url</code> (string): The URL of the created Google Document.</li>\n</ul>\n","urlObject":{"protocol":"https","path":["write","gdoc"],"host":["productmind.trilogy.com"],"query":[],"variable":[]}},"response":[{"id":"990f1532-6279-4f19-a459-e5e3aef8fff1","name":"Example request","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"gdrive_folder_url\": \"https://drive.google.com/drive/folders/1GyazgZsdsjDx9bqy2hMOeDE8yjH25I_C?usp=sharing\",\n  \"filename\": \"Test Markdown Document\",\n  \"markdown_content\": \"# Test Heading\\n\\nThis is a test markdown document.\\n\\n## Subheading\\n\\n- List item 1\\n- List item 2\\n\\n**Bold text** and *italic text*.\"\n} ","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/write/gdoc"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Date","value":"Fri, 28 Mar 2025 09:18:45 GMT"},{"key":"Content-Type","value":"application/json"},{"key":"Content-Length","value":"94"},{"key":"Connection","value":"keep-alive"},{"key":"x-amzn-RequestId","value":"dcc6f9b6-4bfc-4d47-bb4c-a655429398a0"},{"key":"x-amz-apigw-id","value":"IIVpjHRLoAMEt6A="},{"key":"X-Amzn-Trace-Id","value":"Root=1-67e6696f-708d8e7f6c806eee2f972dd5;Sampled=1;Lineage=1:f6c6fa6b:0"}],"cookie":[],"responseTime":null,"body":"{\n    \"doc_url\": \"https://docs.google.com/document/d/1agRa5ioW9PCVyM6EkU2RdvRjcsSjuq2ymr4XOymsDWI\"\n}"}],"_postman_id":"a4836394-904a-49da-918f-9d33e43eab7e"}],"id":"d2c27bc8-ad1f-4e2c-8b65-e9ab45f33750","description":"<p>This folder contains endpoints for writing data to external systems, with a focus on Notion integration. These endpoints enable you to create, append, or replace content on Notion pages programmatically. This feature is particularly useful for scenarios where you want to bring conversations or other dynamic content into your knowledge base, ensuring that ProductMind can both consume and contribute to your existing tools and workflows.</p>\n","_postman_id":"d2c27bc8-ad1f-4e2c-8b65-e9ab45f33750"},{"name":"Convert","item":[{"name":"Convert to Markdown","id":"9af0f420-5d91-4655-ac23-2bbc4e4aa203","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"url\": \"https://drive.google.com/file/d/1LSiSyhH8La9Pm-GQ40wFanOg6Znob-cQ/view?usp=sharing\",\n    \"force_reprocess\": true\n}","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/convert/url","description":"<p>This is a generic endpoint that allows converting any supported file types and file sources to Markdown format.</p>\n<p>It is basically an aggregation of the other Convert methods (the proper one is selected based on the url and used under the hood).</p>\n<h3 id=\"parameters\">Parameters:</h3>\n<ul>\n<li><p><code>url</code> (string, required): The URL of the file that should be converted.</p>\n</li>\n<li><p><code>force_reprocess</code> (boolean, optional): Indicates whether processing should happen even if the results are already cached. Note that this is not currently supported for all file types. <strong>Default</strong>: false</p>\n</li>\n<li><p><code>return_mode</code>(enum, optional): Indicates how the results should be returned:</p>\n<ul>\n<li><p><code>direct</code>: Return the contents (the markdown after conversion)</p>\n</li>\n<li><p><code>s3_url</code>: Return an S3 url pointing to a file that contains the contens (useful for automations passing content around)</p>\n</li>\n<li><p><code>auto</code>(default): Normally returns the results as markdown - there is a special case for large PDFs that get returned as an <code>s3_url</code> above a treshold.</p>\n</li>\n<li><p><code>s3_presigned_url</code> (preview on pr163 env): Return a presigned S3 url to download the data from</p>\n</li>\n</ul>\n</li>\n<li><p><code>optimize_for_tool_use</code> : A special mode where some files are returned without markdown conversion (e.g. CSV, Excel or Google sheet) that can be better used as is by LLMs that can execute python code to read these files. All other files go through the normal conversion process. <strong>Default</strong>: false</p>\n</li>\n</ul>\n<p>All parameters should be passed in the request body as JSON.</p>\n<h3 id=\"supported-data-sources-and-file-formats\">Supported data sources and file formats</h3>\n<p>ℹ️ See notes on permissions below</p>\n<h4 id=\"google-drive\">Google drive</h4>\n<ul>\n<li><p>PDF</p>\n</li>\n<li><p>Google doc</p>\n</li>\n<li><p>Google sheet</p>\n</li>\n<li><p>Word (.docx)</p>\n</li>\n<li><p>Excel (.xlsx)</p>\n</li>\n<li><p>Markdown (.md)</p>\n</li>\n<li><p>Plain text (.text)</p>\n</li>\n<li><p>YAML (.yml or .yaml)</p>\n</li>\n<li><p>MP4</p>\n<ul>\n<li>With transcript next to it or without. See note below for details</li>\n</ul>\n</li>\n<li><p>CSV (.csv)</p>\n</li>\n</ul>\n<h4 id=\"notion\"><strong>Notion</strong></h4>\n<ul>\n<li>Notion pages</li>\n</ul>\n<h4 id=\"postman\"><strong>Postman</strong></h4>\n<ul>\n<li><p>Postman collection</p>\n</li>\n<li><p>Postman folder</p>\n</li>\n</ul>\n<h4 id=\"github\">GitHub</h4>\n<ul>\n<li><p>Markdown (.md)</p>\n</li>\n<li><p>YAML (.yml or .yaml)</p>\n</li>\n<li><p>Plain text (.txt)</p>\n</li>\n</ul>\n<h3 id=\"important-information-for-data-sources\">Important information for data sources</h3>\n<h4 id=\"google-drive-1\">Google drive</h4>\n<blockquote>\n<p><strong>Note:</strong> The Google Drive file must be shared with the <code>cpm-diligence@trilogy.com</code> group for this endpoint to access and process it. </p>\n</blockquote>\n<h5 id=\"videos-with-transcripts\">Videos with transcripts</h5>\n<blockquote>\n<p><strong>Note on permissions:</strong><br />- In order to check and find a transcript file in Google drive next to the video the <a href=\"https://mailto:cpm-diligence@trilogy.com\">cpm-diligence@trilogy.com</a> service account needs to have view access to the folder containing the video and transcript (otherwise we can't check whether there is another file next to the video) </p>\n</blockquote>\n<p>- In order to transcribe a video the <a href=\"https://mailto:cpm-diligence@trilogy.com\">cpm-diligence@trilogy.com</a> service account needs to have access to it, and the video needs to allow viewers to download the video (you can change this on the share dialog under the settings clicking the cog icon). This is sometimes for meeting recordings off by default.</p>\n<h4 id=\"notion-1\">Notion</h4>\n<blockquote>\n<p><strong>Note:</strong> The Notion page must be shared with the ProductMind-Export-Import integration for this endpoint to access and process it.<br />To share the page with the exporter, follow these steps:<br />1. Open the page in Notion.<br />2. Open the 'three dots' menu in the top-right corner.<br />3. Ensure that 'ProductMind-Export-Import' is listed under 'Connections'. If not, add it. </p>\n</blockquote>\n<h4 id=\"postman-1\">Postman</h4>\n<blockquote>\n<p><strong>Note</strong>: The following URL formats are supported for Postman collections:<br />- Workspace folder: <a href=\"https://ws-eng.postman.co/workspace/Platform-Prod%5C~66ec436e-5fcd-43ad-964c-f70d5ca1225f/folder/31124709-c9060ee9-6b7c-4d32-861c-7ff22d5d9c60\">https://ws-eng.postman.co/workspace/Platform-Prod~66ec436e-5fcd-43ad-964c-f70d5ca1225f/folder/31124709-c9060ee9-6b7c-4d32-861c-7ff22d5d9c60</a><br />- Collection: <a href=\"https://ws-eng.postman.co/workspace/ProductMind%5C~4f2b8040-ee72-4afe-92d0-b189c4dac3e9/collection/38070356-941aecfa-a192-46a6-98b0-756a76a4693f?action=share&amp;creator=38070356\">https://ws-eng.postman.co/workspace/ProductMind~4f2b8040-ee72-4afe-92d0-b189c4dac3e9/collection/38070356-941aecfa-a192-46a6-98b0-756a76a4693f?action=share&amp;creator=38070356</a><br />- Workspace folder (alternative format): <a href=\"https://ws-eng.postman.co/workspace/ProductMind%5C~4f2b8040-ee72-4afe-92d0-b189c4dac3e9/folder/38070356-b86b8070-d4d8-44b4-9361-c47d3e2256b2?action=share&amp;source=copy-link&amp;creator=38070356&amp;ctx=documentation\">https://ws-eng.postman.co/workspace/ProductMind~4f2b8040-ee72-4afe-92d0-b189c4dac3e9/folder/38070356-b86b8070-d4d8-44b4-9361-c47d3e2256b2?action=share&amp;source=copy-link&amp;creator=38070356&amp;ctx=documentation</a><br />- Collection (alternative format): <a href=\"https://ws-eng.postman.co/workspace/Platform-Prod%5C~66ec436e-5fcd-43ad-964c-f70d5ca1225f/collection/31124709-d038145a-a2fd-46f9-8cd1-f6024afbbf72\">https://ws-eng.postman.co/workspace/Platform-Prod~66ec436e-5fcd-43ad-964c-f70d5ca1225f/collection/31124709-d038145a-a2fd-46f9-8cd1-f6024afbbf72</a> - Workspace folder (without workspace name): <a href=\"https://ws-eng.postman.co/workspace/4f2b8040-ee72-4afe-92d0-b189c4dac3e9/folder/38070356-5f19b4dd-c3e9-48cd-9383-7d4d030f74ed?action=share&amp;source=copy-link&amp;creator=38070356&amp;ctx=documentation\">https://ws-eng.postman.co/workspace/4f2b8040-ee72-4afe-92d0-b189c4dac3e9/folder/38070356-5f19b4dd-c3e9-48cd-9383-7d4d030f74ed?action=share&amp;source=copy-link&amp;creator=38070356&amp;ctx=documentation</a></p>\n</blockquote>\n","urlObject":{"protocol":"https","path":["convert","url"],"host":["productmind.trilogy.com"],"query":[],"variable":[]}},"response":[{"id":"f89cac05-7e1d-43e1-a5c5-65f9151a07ca","name":"Convert PDF to Markdown (MD)","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"url\": \"https://drive.google.com/file/d/1WKLsFJJn9jwWSkHb_E-kUBllPpAg76ua/view?usp=drive_link\"\n}","options":{"raw":{"language":"json"}}},"url":"https://pr131.productmind.trilogy.com/convert/url"},"status":"OK","code":200,"_postman_previewlanguage":"plain","header":[{"key":"Date","value":"Fri, 22 Nov 2024 17:41:35 GMT"},{"key":"Content-Type","value":"text/markdown; charset=utf-8"},{"key":"Content-Length","value":"3448"},{"key":"Connection","value":"keep-alive"},{"key":"x-amzn-RequestId","value":"945ea601-3d9f-4c6f-afec-a8a5f73d84c2"},{"key":"x-amz-apigw-id","value":"BqNL-GP3IAMEeTw="},{"key":"X-Amzn-Trace-Id","value":"Root=1-6740c24c-2262d4d63852ed127625d70f;Sampled=1;Lineage=1:59f458cb:0"}],"cookie":[],"responseTime":null,"body":"# Page 1\n\n# Contently Creation Features\n\n## G2's #1 Rated Enterprise Content Creation Technology\n\nBuild a team of elite creators with Contently and start creating the content of your dreams. See how our advanced content marketing platform can help you tell stories that engage your audience and drive results.\n\n[TAKE A PRODUCT TOUR >>](#)\n\n## Intelligent Talent Recommendations\n\nBuild a team of award-winning content creators that are perfect for your content program with the help of our Intelligent Talent Recommendation algorithm.\n\nWe match you with the perfect freelancers based on your content strategy so can start telling incredible stories together.\n\n[Schedule a custom demo](#)\n\n[Screenshot of Contently's talent search interface showing a list of talent recommendations on the left side and detailed contributor information on the right. The interface displays various content creators with their profile pictures, recent stories, and last active dates. The layout is clean and organized with clear sections for contributors, details, and invite status.]\n\nContently Creation Features | 1\n\n# Page 2\n\n# Content and Multimedia Editors\n\nCreate content quickly and easily with our content and multimedia editors. Track activity, build custom workflows, and collaborate easily with comment functionality across written content, visual, and video content.\n\nGet a summary of the brief, target audience, and strategy of each story so everyone stays on the same page.\n\n# Automated Content Optimization and Governance\n\nAutomate your content creation checklist with advanced tools that check your content for plagiarism, SEO, reading time, reading level, grammatical issues, and more.\n\nIt's like having editorial superpowers.\n\n[Screenshot of a content editor interface showing an article titled \"3 Problems That Plague Fintech Case Studies\". The interface displays various content optimization tools and metrics including reading time, character count, and readability scores. The editor has a clean, modern design with editing and sharing options.]\n\n# Voice and Tone Analyzer\n\nBring science to the art of brand voice with our Tone Analyzer, powered by IBM Watson.\n\nSee which voice and tone traits engages your audience the most, and then optimize your content to hit the perfect note with real-time analysis\n\nContently Creation Features 2\n\n# Page 3\n\nThe image shows a web interface for what appears to be a content creation platform focused on fintech case studies. The interface displays:\n\n# The Problems With Fintech Case Studies [And How to Fix Them in 2022]\n\nThe page shows a content editor with several sections:\n\n- A main text editing area containing an article about fintech case studies\n- A right sidebar with various content optimization metrics including:\n  - Quality indicators\n  - Optimization scores\n  - Style and tone measurements showing sliders for:\n    - Openness\n    - Conscientiousness \n    - Extraversion\n    - Agreeableness\n    - Emotional range\n\nThe interface has a clean, modern design with a light color scheme and appears to be a specialized content creation tool that helps writers optimize their fintech case study content with AI-powered recommendations and analysis.\n\nAt the bottom of the image, there's a page number indicator showing \"Contently Creation Features 3\"\n\nThe tool seems designed to help content creators write more effective and engaging case studies while maintaining consistent tone and style guidelines."},{"id":"892d26e7-d388-4d9a-b96f-7000e1d870c7","name":"Convert PDF to Markdown (S3)","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"url\": \"https://drive.google.com/file/d/1WKLsFJJn9jwWSkHb_E-kUBllPpAg76ua/view?usp=drive_link\",\n  \"force_reprocess\": false,\n  \"return_mode\": \"s3_url\"\n}","options":{"raw":{"language":"json"}}},"url":"https://pr131.productmind.trilogy.com/convert/url"},"status":"OK","code":200,"_postman_previewlanguage":"plain","header":[{"key":"Date","value":"Fri, 22 Nov 2024 17:40:59 GMT"},{"key":"Content-Type","value":"text/markdown; charset=utf-8"},{"key":"Content-Length","value":"77"},{"key":"Connection","value":"keep-alive"},{"key":"x-amzn-RequestId","value":"ab99c593-6420-4fc7-9e65-4dae7bdb741b"},{"key":"x-amz-apigw-id","value":"BqNGWELUoAMEWHg="},{"key":"X-Amzn-Trace-Id","value":"Root=1-6740c228-71f02b3c51b9a855374810f2;Sampled=1;Lineage=1:59f458cb:0"}],"cookie":[],"responseTime":null,"body":"s3://productmind-convert-to-md/pdf/8277eb4f9db16c0727cfbafd0a3cd009_1_full.md"},{"id":"f02f4d4d-2567-43f5-84f6-6e5ca9eadb38","name":"Convert GDoc to Markdown","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"url\": \"https://docs.google.com/document/d/1-CJEZNzjNq6i_JHA9_9R-8Jrm5FEfzyRFQP_v2esAdY/edit?usp=drive_link\"\n}","options":{"raw":{"language":"json"}}},"url":"https://pr131.productmind.trilogy.com/convert/url"},"status":"OK","code":200,"_postman_previewlanguage":"plain","header":[{"key":"Date","value":"Fri, 22 Nov 2024 17:43:15 GMT"},{"key":"Content-Type","value":"text/markdown; charset=utf-8"},{"key":"Content-Length","value":"1618"},{"key":"Connection","value":"keep-alive"},{"key":"x-amzn-RequestId","value":"502d2637-8450-4d72-9fdd-914f41d672f9"},{"key":"x-amz-apigw-id","value":"BqNbdHrwIAMECHQ="},{"key":"X-Amzn-Trace-Id","value":"Root=1-6740c2af-0020519777f74542756f2903;Sampled=1;Lineage=1:59f458cb:0"}],"cookie":[],"responseTime":null,"body":"# Test gdoc6\n\n# This is an example document that we want to convert to MD\n\n## With a subtitle that is changed now\n\nHe*re is some formatting. **Of this** stuff.* **Bold** and underlined,  \nAnd colors\\!\\!\\!\n\nHere a table\n\n| aaad | frefer | ewfrarfwfr |\n| :---- | :---- | :---- |\n| fasaer | Aerhjeraf aerfhkjaerf | Kllkmklare aerfknleavr |\n\n# A header\n\n## A subheader\n\n### And one more level down \\-2\n\nAnd some text aligned in a few ways  \nLorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent luctus scelerisque finibus. Sed dignissim mauris bibendum enim elementum commodo. Fusce eget ante enim. Sed magna libero, sagittis quis tincidunt nec, mollis quis nisi. In non tempor diam. Fusce consectetur ultrices feugiat. Vestibulum posuere felis sit amet ex ullamcorper, et cursus orci scelerisque.\n\nPraesent mauris nibh, ultricies sit amet rutrum ut, porttitor eget eros. Donec eget nulla mattis, lobortis risus in, sollicitudin nulla. Aenean fringilla nunc nibh, in elementum libero tristique non. Mauris eget quam eleifend, sagittis enim sed, tempor sapien. Donec porttitor consectetur arcu, eu pulvinar orci fermentum vitae. Ut id commodo velit, eget accumsan tortor. Sed lectus nulla, finibus et ex ut, tempor blandit libero.\n\nPellentesque nec lacus pulvinar, dictum augue at, mattis nisl. Vivamus feugiat, lacus eget sodales commodo, urna tortor vulputate purus, eu varius enim m\n\nA numbered list:\n\n1. Item 1  \n2. Item 2  \n3. Afdkjnkdlfnsv  \n4. Knmknkmlkl\n\nA bulleted list:\n\n- Njjaerfaerf  \n- Kklaerf kaerrfko jelrfk: fearfefref  \n- Kemrfklaef\n\n\n  \nTesting some Hungarian: árvíztűrő tükörfúrógép "},{"id":"5e0cf951-4b0a-43b8-b0e4-4597c13f6589","name":"Convert GSheet to Markdown","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"url\": \"https://docs.google.com/spreadsheets/d/19LuYr1MeoS7gHpxn7gaSL6tL2Zb6R4hJndwNZo7ZwcQ/edit?usp=drive_link\"\n}","options":{"raw":{"language":"json"}}},"url":"https://pr131.productmind.trilogy.com/convert/url"},"status":"OK","code":200,"_postman_previewlanguage":"plain","header":[{"key":"Date","value":"Fri, 22 Nov 2024 17:43:39 GMT"},{"key":"Content-Type","value":"text/markdown; charset=utf-8"},{"key":"Content-Length","value":"398"},{"key":"Connection","value":"keep-alive"},{"key":"x-amzn-RequestId","value":"ac40d67c-d59f-448d-9b3b-150e89828683"},{"key":"x-amz-apigw-id","value":"BqNfLEOdoAMEJ5Q="},{"key":"X-Amzn-Trace-Id","value":"Root=1-6740c2c7-33fa2c767f94bfb025e98a49;Sampled=1;Lineage=1:59f458cb:0"}],"cookie":[],"responseTime":null,"body":"# Just a test sheet\n\n## First sheet\n\ncolumne 1\n\n## priorities\n\n\n\n| Feature | Category | Status | Owner | Size | Launch | Notes |\n| --- | --- | --- | --- | --- | --- | --- |\n| abbavecr | Category 1 | Not started |  | XS | Q1 |  |\n| klklkj aferkjh | Category 2 | In progress |  | S | Q2 |  |\n| kkds | Category 3 | Blocked |  | M | Q3 |  |\n| dsjajknasd | Category 4 | Launched |  | L | Q4 |  |\n\n\n\njk\n\n"},{"id":"a7d7695c-77df-4564-b93c-20b14472ce22","name":"Convert Word to Markdown","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"url\": \"https://docs.google.com/document/d/1W8bji2KmP3ZcxZqIupXehKiVoI5Dhu_-/edit?usp=drive_link&ouid=107958425101123608031&rtpof=true&sd=true\"\n}","options":{"raw":{"language":"json"}}},"url":"https://pr131.productmind.trilogy.com/convert/url"},"status":"OK","code":200,"_postman_previewlanguage":"plain","header":[{"key":"Date","value":"Fri, 22 Nov 2024 17:44:32 GMT"},{"key":"Content-Type","value":"text/markdown; charset=utf-8"},{"key":"Content-Length","value":"13235"},{"key":"Connection","value":"keep-alive"},{"key":"x-amzn-RequestId","value":"203b49c0-b3c5-4881-a128-8ba1d5144474"},{"key":"x-amz-apigw-id","value":"BqNm0GOvIAMEe3Q="},{"key":"X-Amzn-Trace-Id","value":"Root=1-6740c2f7-7f7ac55e7c067f5c2c2e1d8b;Sampled=1;Lineage=1:59f458cb:0"}],"cookie":[],"responseTime":null,"body":"# Copy of Follow-up questions - Interviewstream_IVSAnswersv2\n\n# Follow-up questions \\- Interviewstream\n\n1. **Pricing**  \n   1. What do customers purchase in terms of units, both education and non-education?\n\n      *For education, our understanding is that customers purchase a certain number of interviews which is estimated based on the current number of FTEs for that district (as opposed to the number of FTEs they plan to hire).*   \n      \n\n   *The majority of US education customers\\* purchase a license w/unlimited interviews. Pricing/costs are based on FTE’s, which is also how their ATS systems and hiring systems set costs typically. The rationale for FTE-basis, outside of this is pricing they are used to, is that you can assume a minimum of 20-25% FTE turnover annually (teacher turnover is \\~30% annually in the US). Pricing tiers are set with each partner (i.e. Powerschool, Frontline) based on FTE ranges with custom pricing for “the largest” school districts.  Essentially- the FTE is a proxy for total interviews expected to be held annually.*   \n     \n   *Canadian schools are a bit different w/conversion in costs/hiring/maturity of market in technology use. Our partner pricing table with applytoeducation is based on a % of their total spend with applytoeducation on hiring related products (i.e. ATS, job boards). This is also an unlimited license just worth noting that the way we determine pricing is different (ATE does use a base of FTE for their pricing so ultimately the construct is similar).  Prior to this partnership starting in 2023, Canadian schools were priced based on FTE once US education pricing was updated in 2022\\.*   \n     \n   *\\*There are some exceptions, not in the majority, of education clients who either (a) signed a long-term contract prior to 2022 where pricing was changed as noted above, or (b) that are not with partners and/or due to budget constraints needed a lower cost.  For those that signed long term contracts prior to 2022, they are on unlimited licenses based on pricing set from prior revenue team and once contract is renewing, we re-establish pricing. For those districts that needed lower costs and signed post 2022, we will then apply interview limits to their contract.  Any exceptions are outlined in the contracts/order forms and are reviewed in a similar manner with the account as noted below for non-education clients.*\n\n        \n      *For non-education, our understanding is that customers purchase a certain number of interviews which is estimated based on the number of interviews expected or the number of scheduled events.*  \n      \n\n   *That is correct, the majority of non-education clients that are under $20,000 in ARR have set limits for their on demand interviews held or scheduled events sent. Over $20,000, which is NOT many accounts, have unlimited licenses. As noted above, there are a handful of exceptions to this however again, it is a legacy account or a specifically outlined part of the annual contract.* \n\n   2. Confirm or correct the following understanding:  \n      *Customers purchase X number of interviews for 1 year (or multi years).*  \n      *If they use it all up, an upsell is discussed with customers. If they do not use it, nothing happens, i.e. customers are not refunded.*   \n      \n\n   *Correct re: upsell. During QBRs, usage is discussed.  If a client is approaching the limit, they have an option to pay for the annual overuse as a 1x fee at the same rate per interview OR “buy up” to another tier.*   \n     \n   *Correct re: refunds. If limits are not reached, there is no refund. Limits are worded as “up to X interviews held/etc in an annual term.”*\n\n        \n      *What happens if they go over without renegotiating \\- do you just sell them additional usage at the same base rate?*   \n      \n\n   *See above, yes.  Note- this is uncommon.  In all recent situations where usage limits have been exceeded, client has renegotiated to a different tier of pricing during quarterly or upcoming annual term.* \n\n2. **Cost savings**  \n   1. Can you quantify productivity increase when customers use interviewstream?\n\n      *You mentioned that customers measure ROI as “time saved”. We would like to understand from a typical customer example, how much time was saved (ideally separately for education and non-education). E.g., for much back-and-forth on email/phone, a recruiter saves when using the scheduler, and how many such events a recruiter typically has in a month.*  \n      \n\n   *Please see additional attachments for a few sample “real” ROI calculators provided based on prospect/customer conversations.*  \n\n        \n   2. In case actual cost savings/offsets are coming from interviewstream, if you are aware of such an example, can you please quantify them and state if the cost (budget item) was reduced? E.g. for Education,since principals are the interviewers, we imagine it only translates into a soft cost-saving (represented by a productivity boost in the principal’s time), while for large enterprises with multiple recruiters, the time saved across scheduling and syncing interview could accrue to be big enough to save a full recruiting FTE (related question \\- how big would the company have to be/pay for the product for this to be true)\n\n   *Please see ROI calculators for estimated savings.  At this time, it is not common for clients to share the “final savings” however some are noted in our case studies which can be found here- [https://interviewstream.com/resources/case-studies/](https://interviewstream.com/resources/case-studies/)* \n\n   \n\n   *To date, I have rarely seen a company with at least 100 employees not see significant potential ROI by deploying on demand and/or scheduler.*\n\n      \n\n3. **Product deployment**  \n   1. Can you describe the typical deployment process for larger customers, step-by-step?\n\n   *Here is the typical implementation timeline provided to a larger customer. As discussed live, the timeline may be adjusted once discussed or if an integration is more “custom” overall.*\n\n      \n\n| Implementation Timeline |  |\n| ----- | ----- |\n| Description | Estimated Timeline |\n| Kick off meeting to discuss timelines, business objectives, expectations IT requirements / documentation / whitelisting | Week 1 |\n| Configuration of interviewstream platform settings and integration Client platform branding, integration setup continued  | Week 2-3 |\n| Platform training and workflow creation  | Weeks 4-6 |\n| User acceptance testing Go-live in production  | Weeks 7-9 |\n\n      \n\n2. What is the required time for deployment of a fully-fledged product? Measured in hours or days of active work by professional services, support, or engineering. And please mention how many people are typically involved. \n\n   \n\n   *For a stand-alone or standard integration client, the product can be fully deployed within less than a day, however most clients still follow a timeline similar to the the implementation timeline above given internal trainings/etc.* \n\n   \n\n   *Unless custom\\*, the primary person deploying/implementing an account at interviewstream is the Customer Success Manager (CSM).  Implementing an account in interviewstream takes at most a few hours of their time. Requests for customization/branding/importing data from prior system/etc. from the client may extend this time frame, however training and conversations with the client are the bulk of the CSMs time during the implementation process.* \n\n   \n\n   *\\*If custom or unique, which is rare, our CTO or VP, Client Services may get involved for a few hours of brainstorming. The product does not require technical involvement in implementation unless there is something custom overall.  If clients have a custom install that goes beyond a few hours of meetings and follow ups, we scope the work with them and charge additional one-time fees (this is incredibly rare).* \n\n   \n\n   3. Are there usually specific integrations required (e.g. ATS)? If yes, are these integrations fully custom (i.e. if customer churns, that custom work is completely gone and would need to be done from scratch)?  \n      \n\n   *As noted in the customer file already provided, the majority of our clients are integration in some fashion. The majority are not “custom” but are proprietary to interviewstream. A few are exclusive partnerships- i.e. Frontline and applytoeducation- and others i.e. Workday, SAP, Taleo are more complex and unique to the client. The handful of OpenAPI or custom integrations are completely unique to the clients involved.*  \n     \n   *If the customer churns and wanted to move over to a new system, they would have to work with their new partner to establish an integration independent of the above and yes, the work would have to be done by the new partner or client.* \n\n4. **Competitive landscape**  \n   1. What makes interviewstream more competitive in the Education segment? What is unique about the product that competitors do not have? Please list all competitive advantages and elaborate on them.  \n      \n\n   *The core differentiators for interviewstream in the education segment can be found on [this page](https://interviewstream.com/industries/k12/) are as follows.  interviewstream has:*  \n- *Partnerships and embedded integrations with all key ATS systems used by US and Canadian K-12 school districts/boards today:*   \n  * *Exclusive partnership and uniquely embedded integration with Frontline Education (ATS), one of the two leading ATS systems in the US K-12 market today*  \n  * *Exclusive partnership and integration with applytoeducation, the leading ATS in Canada, with market share in over 90% of Canadian school boards*  \n  * *Partnership and a strong integration to PowerSchool, the second leading ATS system in the US K-12 market today*  \n  * *And if a district is not using any of the above, a strong OpenAPI and Chrome extension option in place*  \n- *Intentional application of AI and analysis in our technology tied to creating efficiencies, without potentially introducing bias or decision direction*  \n  * [*AI Question Assist*](https://interviewstream.com/resources/blog/new-features-from-interviewstream/)*, [Recruit Assist](https://interviewstream.com/ai-recruiting-assistant/), and soon to be launched, Simple Summary*  \n  * *interview insights which applies over 10 years of data to benchmark and improve your hiring process, using millions of interviews worth of data to determine ways to improve the process and recommend*   \n- *Enhanced information security and compliance processes and certifications with K-12 in mind*  \n  * *SOC 2 Type 2, GDPR/PIPEDA data privacy/compliance*  \n  * *Deep experience working with school district teams to handle DPA’s and PIA’s for districts/boards*  \n  * *Ability to create workflows in interviewstream to support highly compliant hiring processes*  \n- *20 years of experience in K-12*   \n  * *Unique workflows designed for and with our K-12 districts and boards including specific templates for onboarding new teachers and administrators and preset templates curated for K-12’s specific use cases.*  \n  * *Customer success team members with over 10 years of experience in deploying and enhancing hiring processes in partnership with districts and boards*  \n      \n  2. For the Scheduler, is there an advanced feature (or features) that competitors (direct competitors or indirect competitors like Calendly) do not have? If yes, please elaborate on that feature.   \n     \n\n  *advanced scheduler has many great features and is a very competitively priced tool however the two features discussed that is important to our clients when considering options is (1) highly customizable landing pages and (2) automatic assignment of an agent/team member to an open slot in a complex scheduling event (i.e. multi-location, multiple potential team members to fill the slot, variable time slots). This will be much easier to understand in a live demo.  More high level information about advanced scheduler can be found [on this page](https://interviewstream.com/interview-scheduler-advanced/) and [in this article](https://interviewstream.com/resources/blog/interview-scheduling/).* \n\n       \n  3. For the Interview Builder, is there an advanced feature (or features) that competitors do not have? If yes, please elaborate on that feature.\n\n\n*interview builder, as noted previously, is a stand-alone product that has 3 active*   \n*clients.  There are two primary differentiators from competitive products- (1) there*   \n*is a strong curriculum program (HireBar) for hiring training tied to this platform*   \n*license that can be used to certify an organization’s team and (2) interview*   \n*guides built can be customized and downloaded in a variety of formats for*   \n*distribution to disparately located teams.* \n\n*The majority of interview builder’s key features can be found in our platform*  \n*through the question library and core on demand solution and in the new feature,*   \n*AI Question Assist.*\n\n*We do not actively seek new clients or present this as a primary new business*   \n*Solution, however it is a key solution, requiring limited maintenance for the 3*   \n*clients actively using it.* "},{"id":"57f8e101-867d-497a-96f8-b82d37b34dd5","name":"Convert Excel to Markdown","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"url\": \"https://docs.google.com/spreadsheets/d/1WF2KHMPulpin70CA1o6vH2-ZAhKrsm92/edit?usp=drive_link&ouid=107958425101123608031&rtpof=true&sd=true\"\n}","options":{"raw":{"language":"json"}}},"url":"https://pr131.productmind.trilogy.com/convert/url"},"status":"OK","code":200,"_postman_previewlanguage":"plain","header":[{"key":"Date","value":"Fri, 22 Nov 2024 17:44:58 GMT"},{"key":"Content-Type","value":"text/markdown; charset=utf-8"},{"key":"Content-Length","value":"356"},{"key":"Connection","value":"keep-alive"},{"key":"x-amzn-RequestId","value":"d6b24e73-707a-4353-a1b0-78a79b87ed29"},{"key":"x-amz-apigw-id","value":"BqNr6H8VIAMEjKg="},{"key":"X-Amzn-Trace-Id","value":"Root=1-6740c318-11ab36e846a6e7494e3065d1;Sampled=1;Lineage=1:59f458cb:0"}],"cookie":[],"responseTime":null,"body":"# Demo excel file\n\n## prios\n\n\n\n| Feature | Category | Status | Owner | Size | Launch | Notes |\n| --- | --- | --- | --- | --- | --- | --- |\n| abbavecr | Category 1 | Not started |  | XS | Q1 |  |\n| klklkj aferkjh | Category 2 | In progress |  | S | Q2 |  |\n| fgg | Category 3 | Blocked |  | M | Q3 |  |\n| gggghhg | Category 4 | Launched |  | L | Q4 |  |\n\n\n\n"},{"id":"7d366773-8d35-41d5-adbd-b4fd346d04c2","name":"Convert Markdown to Markdown","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"url\": \"https://drive.google.com/file/d/1blDo5Lpb4s0B4L2cAyCu2-c4Xn5iIec2/view?usp=drive_link\"\n}","options":{"raw":{"language":"json"}}},"url":"https://pr131.productmind.trilogy.com/convert/url"},"status":"OK","code":200,"_postman_previewlanguage":"plain","header":[{"key":"Date","value":"Fri, 22 Nov 2024 17:45:25 GMT"},{"key":"Content-Type","value":"text/markdown; charset=utf-8"},{"key":"Content-Length","value":"2882"},{"key":"Connection","value":"keep-alive"},{"key":"x-amzn-RequestId","value":"fe152074-b604-4812-a961-066f50a02d98"},{"key":"x-amz-apigw-id","value":"BqNwAFIroAMEA9Q="},{"key":"X-Amzn-Trace-Id","value":"Root=1-6740c332-0f81633f5e1c7abd1a770362;Sampled=1;Lineage=1:59f458cb:0"}],"cookie":[],"responseTime":null,"body":"\n\n| Author | Akos Orban |  |  |\n| :---- | ----- | :---- | :---- |\n| **Product** | Trilogy: Gen AI-\\>ProductMind |  |  |\n| **Unit** | **[TAI-25](https://ws-lambda.atlassian.net/browse/TAI-25)** |  |  |\n| **Problem \u000bStatement** | **What**: |  | Sync is not picking up new documents |\n|  | **When and Where**: |  | For some notion pages children are not picked up during synchronization |\n| **Why Why Analysis** |  | **Question**: | Why are some children pages missing? |\n|  |  | **Answer**: | Because they are not getting synced in the updateCompaniesAndSync  state machine |\n|  |  | **Evidence**: | Example execution: ![][image1] |\n|  |  | **Question**: | Why are they not picked up in the recurring sync? |\n|  |  | **Answer**: | Because they are not picked up in the syncAndConvertFoldersAndFiles state machine |\n|  |  | **Evidence**: | The state machine is executed with only 2 notion pages (expecting 3\\) ![][image2] |\n|  |  | **Question**: | Why is the state machine not picking up the missing page? |\n|  |  | **Answer**: | The listing subpages lambda returns only the 2 pages it got as input. |\n|  |  | **Evidence**: | ![][image3] |\n|  |  | **Question**: | Why is the list subpages lambda not finding the 3rd subpage? |\n|  |  | **Answer**: | Because the get\\_nested\\_pages in (functions/pythonLambdas/lib/services/notion/notion_service.py) doesn’t find the subpages of the root notion page |\n|  |  | **Evidence**: | ![][image4] |\n|  |  | **Question**: | Why the get\\_nested\\_pages doesn’t return the subpages? |\n|  |  | **Answer**: | Because the function iterates through the page content to find the content block with the subpages links, but only in the first 100 returned blocks because the result from Notion API is paginated. As this page is long the matching block would be later and would need to be fetched as the next page of results. |\n|  |  | **Evidence**: | ![][image5] |\n| **Root Cause** | Since Notion API doesn’t provide a great way to get the subpages the current implementation iterates through the whole page content to find the subpages links, which are at the end of the pages. But it doesn’t take into account paginated page content response from Notion API and only checks the first 100 blocks. On a long page this is not enough. |  |  |\n| **Related \u000bTech Debt** | no |  |  |\n| **Fix** | Will need to keep loading next pages with the content until we reach the end to find all subpage links. Ideally Notion would provide a simple API for this use-case, but some research indicates that such API doesn’t exist. |  |  |\n| **Process\u000bInsights** | Need to test solution with long contents also as that could cause some pagination issues as here (maybe some timeouts or slow-downs in other cases) |  |  |\n| **Lessons Learned** | Notion API is not very useful, need to be careful with operations using it and make sure to test for edge cases. |  |  |\n\n\n"},{"id":"13d353e5-292d-479a-b1f4-b3bfa6e58328","name":"Convert TXT to Markdown","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"url\": \"https://drive.google.com/file/d/16SX7QyP3lN7Vf6lVyuFD4I3AEgpZPtzE/view?usp=drive_link\"\n}","options":{"raw":{"language":"json"}}},"url":"https://pr131.productmind.trilogy.com/convert/url"},"status":"OK","code":200,"_postman_previewlanguage":"plain","header":[{"key":"Date","value":"Fri, 22 Nov 2024 17:45:56 GMT"},{"key":"Content-Type","value":"text/markdown; charset=utf-8"},{"key":"Content-Length","value":"145"},{"key":"Connection","value":"keep-alive"},{"key":"x-amzn-RequestId","value":"93fbfbdd-6a29-43c2-bbbf-65baaedc22dd"},{"key":"x-amz-apigw-id","value":"BqN02EnjoAMEchg="},{"key":"X-Amzn-Trace-Id","value":"Root=1-6740c351-19a2362774274c4c0914f251;Sampled=1;Lineage=1:59f458cb:0"}],"cookie":[],"responseTime":null,"body":"This is just an example text doc\n\n\n\nLorem ipsum dolor sit amet\nLorem ipsum dolor sit amet\n\nLorem ipsum dolor sit amet\n\nLorem ipsum dolor sit amet"},{"id":"ace3e908-e376-4409-8c48-0f496d697377","name":"Convert YAML to Markdown","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"url\": \"https://drive.google.com/file/d/119DN4YhWZwHD02PuJSB4wZq8d5HzJ5w_/view?usp=drive_link\"\n}","options":{"raw":{"language":"json"}}},"url":"https://pr131.productmind.trilogy.com/convert/url"},"status":"OK","code":200,"_postman_previewlanguage":"plain","header":[{"key":"Date","value":"Fri, 22 Nov 2024 17:46:36 GMT"},{"key":"Content-Type","value":"text/markdown; charset=utf-8"},{"key":"Content-Length","value":"103702"},{"key":"Connection","value":"keep-alive"},{"key":"x-amzn-RequestId","value":"144c6fc2-3e44-4a70-918e-bdac57be9be0"},{"key":"x-amz-apigw-id","value":"BqN7DGQMIAMEcjQ="},{"key":"X-Amzn-Trace-Id","value":"Root=1-6740c379-346a46f14b9f985873674471;Sampled=1;Lineage=1:59f458cb:0"}],"cookie":[],"responseTime":null,"body":"openapi: 3.0.3\ninfo:\n  title: Subscription management API\n  version: 0.4.0\n  description: \"It's necessary to [generate a JWT Token](https://rapid-engineering.atlassian.net/wiki/spaces/SI/pages/1938358285/Generate+JWT+token) and use it as authorization method in the api.\"\n  license:\n    name: Copyright\n  contact:\n    email: rp-si@trilogy.com\n    name: RP Sales Infrastructure\nservers:\n  - url: /api/v1\n  - url: /test/api/v1\ntags:\n  - name: Customer\n  - name: Product catalog\n  - name: Subscription\n  - name: Report Usage\n  - name: Integration internal\n  - name: Invoices\n  - name: UI customer\n  - name: UI storage\n  - name: UI subscription\npaths:\n  /subscriptions:\n    get:\n      summary: Get Customer Subscriptions\n      operationId: getCustomerSubscriptions\n      description: |-\n        Retrieve subscription list filtered by parameters and by productVariantCode and productFamilyCode (pfc and pvc) set in authentication token.\n        Subscriptions can also be filtered by subscription status, e.g. Active, Pending_Activation. \n\n        A validation check for customer id present in JWT Token will be performed to prevent customers from fetching subscriptions of other customers.\n      parameters:\n        - schema:\n            type: string\n          in: query\n          name: customerId\n          description: Required for non-customer (Admin) token\n        - schema:\n            type: array\n            items:\n              $ref: '#/components/schemas/StatusEnum'\n          description: 'For more than one parameter, it needs to be indexed. Ex: statuses[0]=ACTIVE&statuses[1]=DRAFT'\n          style: form\n          in: query\n          name: statuses\n        - schema:\n            type: number\n          in: query\n          name: maxResults\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: array\n                items:\n                  $ref: '#/components/schemas/Subscription'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          description: Not Found\n      tags:\n        - Subscription\n  /integration/product:\n    get:\n      summary: Get Product Integration Record from NetSuite\n      operationId: get-integration-product\n      description: |-\n        Retrieve Product Integration Record for Product family (e.g. DNN) and Product Variant (e.g. SA-CUS) in JWT token\n\n        Only allowed with Admin JWT token (i.e. with padm=true flag)\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: array\n                items:\n                  $ref: '#/components/schemas/ProductIntegration'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          description: Not Found\n      tags:\n        - Integration internal\n      security:\n        - PrivilegedToken: []\n  /integration/reportUsage:\n    post:\n      summary: Report Usage/consumption for Subscription's usage type items.\n      operationId: post-integration-report-usage\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: array\n              description: ''\n              items:\n                type: object\n                description: ''\n                properties:\n                  subscriptionId:\n                    type: number\n                    description: Subscription ID to report usage against.\n                  itemCode:\n                    type: string\n                    description: Code of item with type usage. If subscription has more than one item with such code lineNumber must be specified\n                  quantity:\n                    type: number\n                    description: Decimal usage quantity\n                  lineNumber:\n                    type: integer\n                    description: Used if more than one item with same code in subscription. Ignored otherwise\n                  usageDate:\n                    type: string\n                    format: date\n                    description: Date of usage. Subscription must be active on this date\n                required:\n                  - subscriptionId\n                  - itemCode\n                  - quantity\n                  - usageDate\n            x-examples:\n              example-1:\n                value:\n                  - subscriptionId: string\n                    unit: string\n                    quantity: 0\n                    itemId: string\n        description: 'List of usages to report. It can be for same or for different subscriptions/items/dates. '\n      responses:\n        '200':\n          $ref: '#/components/responses/PartialResponse'\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n      description: |-\n        Report consumption for usage based items which should be paid in arrears based on real usage. \n        It is assumed that product manages online numbers and use this method scheduled with batch of items across many customers.\n        Method may return with partially success response, failed records will be reported in errors array.\n      tags:\n        - Report Usage\n      security:\n        - PrivilegedToken: []\n    parameters: []\n  /integration/searchCustomer:\n    post:\n      summary: 'Integration: Search customer in NetSuite'\n      operationId: post-customer-search\n      description: |-\n        Retrieve customers based upon criteria specified in the request body. \n\n        Only allowed with padm=true (Admin) in JWT token\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              properties:\n                firstName:\n                  type: string\n                  maxLength: 32\n                lastName:\n                  type: string\n                  maxLength: 32\n                email:\n                  type: string\n                  format: email\n                companyName:\n                  type: string\n                contactEmail:\n                  type: string\n                  format: email\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: array\n                items:\n                  $ref: '#/components/schemas/Customer'\n        '401':\n          $ref: '#/components/responses/Error'\n        '404':\n          description: Not Found\n      tags:\n        - Integration internal\n      security:\n        - PrivilegedToken: []\n  /integration/netsuiteRelay:\n    post:\n      summary: 'Integration: Passes any request to the NetSuite instance'\n      operationId: post-netsuite-relay\n      description: |-\n        Make a POST request to the NetSuite URL with the body provided.\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              properties:\n                targetNSRequest:\n                  type: string\n                  enum:\n                    - generate_quote\n                    - renewal_order\n                payload:\n                  type: object\n              required:\n                - targetNSRequest\n                - payload\n            example:\n              targetNSRequest: 'generate_quote'\n              payload:\n                op: 'quote.create'\n                productFamilyCode: 'GEN'\n                productVariantCode: 'OP-SUB'\n                customerId: '2861'\n                subscriptionId: 441817\n                content: null\n      responses:\n        '200':\n          description: Success. The response contains the data returned by  NetSuite.\n          content:\n            application/json:\n              schema:\n                type: object\n        '401':\n          description: Security token is incorrect\n          content:\n            application/json:\n              schema:\n                type: object\n                properties:\n                  message:\n                    type: string\n      tags:\n        - Integration internal\n  /subscription/{subscriptionId}/renewal:\n    get:\n      summary: Get the plan and items for renewal.\n      operationId: get-subscription-renewal-info\n      description: Retrieve the code, items and quantity of the latest active subscription plan based on the given input parameters.\n      parameters:\n        - name: subscriptionId\n          in: path\n          required: true\n          schema:\n            type: integer\n        - name: productTier\n          in: query\n          required: true\n          schema:\n            $ref: '#/components/schemas/ProductTierEnum'\n        - name: supportLevel\n          in: query\n          required: true\n          schema:\n            $ref: '#/components/schemas/SupportLevelEnum'\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: object\n                properties:\n                  plan:\n                    type: object\n                    description: the plan\n                    properties:\n                      code:\n                        type: string\n                      description:\n                        type: string\n                      name:\n                        type: string\n                  items:\n                    type: array\n                    items:\n                      type: object\n                      description: the item\n                      properties:\n                        code:\n                          type: string\n                        quantity:\n                          type: number\n                          description: The quantity to be renewed. If the product has a minimnum quantity and current quantity is less than that, the minimum quantity will be returned.\n                        originalQuantity:\n                          type: integer\n                          description: The original quantity before renewal.\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n        '500':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Subscription\n  '/subscription/{subscriptionId}':\n    parameters:\n      - schema:\n          type: string\n        name: subscriptionId\n        in: path\n        required: true\n    get:\n      summary: Get Subscription against a subscription ID\n      operationId: get-subscription-subscriptionId\n      description: Retrieve a subscription against the subscription ID. A validation check for customer id present in JWT Token will be performed to prevent customers from fetching subscriptions of other customers.\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Subscription'\n        '401':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Subscription\n    put:\n      summary: Update an Active or Draft Renewal Subscription.\n      operationId: put-subscription-subscriptionId\n      description: |-\n        Make updates to an Active Subscription or a Draft Renewal Subscription against the Subscription ID provided.\n\n        For Draft Renewal Subscription - Update the existing Draft Subscription if it's just a qauntity change or in case of Subscription Plan change, delete the old draft and generate a new Draft Subscription (returns a new Subscription Id). Keep it in Draft Status until the Quote is accepted.\n\n        For Active Term Subscription Upgrades - Generates a New Draft Subscription with requested changes (returns a new draft Subscription Id). Draft Subscription Start, End Dates and Initial Term will be same as original subscription. The new Draft Subscription with changes is linked to original subscription through a naming convention containing the Original Subscription ID.\n        Customer will retain his current price discounts percentage in case of upgrades. \n\n        For Active Term Subscription Downgrades - Downgrades to Active Term Subscriptions are not allowed.\n\n        For Active Evergreen Subscription - The upgrades to Quantity, Edition or Success Level are applicable immediately, and the downgrades will be applied on the next billing cycle. Evergreen subscriptions do not need to go through quote acceptace process to be activate or updated.\n\n        For Trial Subscription - Trial Subscription Upgrade to the paid subscription follows the same process of active subscription update. If the input of this API is Trial Subscription ID, a draft subscription will be created with required changes.\n      requestBody:\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/UpdateSubscriptionConfiguration'\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Subscription'\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '404':\n          description: Not Found\n      tags:\n        - Subscription\n    patch:\n      summary: Update subscription status e.g. Activate a Draft Subscription\n      operationId: patch-subscription-subscriptionId\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Subscription'\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n      description: |-\n        Activate the subscription against the subscription ID provided in API input.\n\n        If Subscription is an Evergreen Subscription - Then activate the subscription skipping the Quote Acceptance check. \n\n        If Subscription is a Term Subscription - Then activate after verifing if the Quote is accepted, else return error.\n\n        If it's an upgrade scenario, then Activation will also deactivate the old Subscription after activating the upgraded subscription.\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              properties:\n                status:\n                  type: string\n              required:\n                - status\n            examples:\n              example-1:\n                value:\n                  status: ACTIVE\n      tags:\n        - Subscription\n  /customer:\n    get:\n      summary: Get Customer details\n      operationId: get-customer\n      description: Retrieve customer details for customer ID present in JWT Token or specified in input parameter in case of Admin JWT Token.\n      parameters:\n        - schema:\n            type: string\n          in: query\n          name: customerId\n          description: Required if cid is not set in JWT Token.\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Customer'\n        '401':\n          $ref: '#/components/responses/Error'\n        '404':\n          description: Not Found\n      tags:\n        - Customer\n    put:\n      summary: Update Customer details\n      operationId: put-customer\n      description: Update the customer information in NetSuite with the information specified in the request body\n      requestBody:\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/Customer'\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: string\n              example: customerId\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          description: Not Found\n      tags:\n        - Customer\n    patch:\n      summary: Partial update of a customer\n      operationId: patch-customer\n      description: |-\n        Partial update of the customer information in NetSuite based on the request body.\n        - An undefined property will be ignored.\n        - A property set to null will be emptied.\n        - A customer can update its own record.\n        - A customer can update only the shipping address of a related end-user, based on its draft subscriptions.\n      requestBody:\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/Customer'\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: string\n              example: customerId\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          description: Not Found\n      tags:\n        - Customer\n    post:\n      summary: Create a new customer in NetSuite\n      operationId: post-customer\n      description: |-\n        Create a new customer in NetSuite with the information provided in the request body.\n\n        Only allowed with padm=true in JWT token\n      requestBody:\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/Customer'\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: string\n              example: customerId\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Customer\n      security:\n        - PrivilegedToken: []\n  /customer/statement:\n    get:\n      summary: Retrieve customer statement\n      operationId: get-customer-statement\n      description: Retrieve the statement for the customer ID present in JWT Token or specified in input parameter in case of Admin JWT Token.\n      parameters:\n        - schema:\n            type: string\n          in: query\n          name: customerId\n          description: Required if cid is not set in JWT Token.\n        - schema:\n            type: string\n          in: query\n          name: startDate\n          description: Optional. The start date of the statement period with format 01-Jan-2021.\n          required: false\n      responses:\n        '200':\n          description: Customer Statement in base64.\n          content:\n            application/pdf:\n              schema:\n                type: string\n                format: byte\n                description: base64-encoded PDF file\n              example: base64 string\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Customer\n  /customer/latestSignedQuote:\n    get:\n      summary: Retrieve customer latest signed quote\n      operationId: get-customer-latest-signed-quote\n      description: Retrieve the latest signed quote for the customer ID present in JWT Token or specified in input parameter in case of Admin JWT Token.\n      parameters:\n        - schema:\n            type: string\n          in: query\n          name: customerId\n          description: Required if cid is not set in JWT Token.\n        - schema:\n            type: string\n          in: query\n          name: endUserId\n          description: Optional. The end user id in case of a reseller to get the latest signed quote for a specific end user.\n          required: false\n      responses:\n        '200':\n          description: Latest signed quote in base64.\n          content:\n            application/pdf:\n              schema:\n                type: string\n                format: byte\n                description: base64-encoded PDF file\n              example: base64 string\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Customer\n  /subscriptionPlans:\n    get:\n      summary: List available subscription plans\n      operationId: get-subscriptionPlan\n      description: Retrieve Subscription Plans for a product family (e.g. DNN) and product variant (SA-CUS) present in JWT token.\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: array\n                items:\n                  $ref: '#/components/schemas/SubscriptionPlan'\n        '401':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Product catalog\n  /subscriptionPlans/latestCode:\n    get:\n      summary: Get the latest subscription plan code\n      operationId: get-subscriptionPlans-latestCode\n      description: Retrieve the code of the latest active subscription plan based on the given input parameters.\n      parameters:\n        - name: productTier\n          in: query\n          required: true\n          schema:\n            $ref: '#/components/schemas/ProductTierEnum'\n        - name: supportLevel\n          in: query\n          required: true\n          schema:\n            $ref: '#/components/schemas/SupportLevelEnum'\n        - name: isSupport\n          in: query\n          required: true\n          schema:\n            type: boolean\n      responses:\n        '200':\n          description: OK\n          content:\n            text/plain:\n              schema:\n                type: string                \n                description: The subscription plan code.\n                example: DNN CustomerCloud EVOQ, STANDARD EDITION, GOLD SUCCESS-002\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n        '500':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Product catalog\n  /products:\n    get:\n      summary: Get list of products and variants\n      operationId: get-product\n      description: List available products based on Product Family Code and Product Variant in JWT Token\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: array\n                items:\n                  $ref: '#/components/schemas/ProductCoordinates'\n        '401':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Product catalog\n  /invoices:\n    get:\n      summary: List customer invoices\n      operationId: get-invoice\n      description: Retrieve customer invoices from NetSuite filtered by input parameters. Invoices returned also contain the Stripe Invoice Payment Link along with other invoice details.\n      parameters:\n        - schema:\n            type: string\n          in: query\n          name: customerId\n          description: Required for non-customer token\n        - schema:\n            type: string\n          in: query\n          name: subscriptionId\n        - schema:\n            type: string\n          in: query\n          name: startDate\n        - schema:\n            type: string\n          in: query\n          name: endDate\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: array\n                items:\n                  $ref: '#/components/schemas/InvoiceInfo'\n        '401':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Invoices\n  /subscription/preview:\n    post:\n      summary: Calculate subscription pricing for a new subscription purchase.\n      operationId: post-subscription-preview\n      description: 'Calculate subscription prices a customer will be charged for selected Product Edition, Support Plan and Add-Ons with intended quantities.'\n      requestBody:\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/BaseSubscriptionConfiguration'\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Preview'\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Subscription\n  '/subscription/preview/{subscriptionId}':\n    parameters:\n      - schema:\n          type: string\n        name: subscriptionId\n        description: 'Id of an active subscription in case of a upgrade/downgrade, or Id of a Draft Renewal Subscription when calculating prices for a subscription renewal.'\n        in: path\n        required: true\n    post:\n      summary: Calculate subscription pricing for active subscription update or subscription renewal.\n      operationId: post-subscription-preview-susbscriptionId\n      description: 'Calculate final price after applying discounts (if applicable) for Subscription Upgrades, Downgrades or Renewals.'\n      requestBody:\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/ExtendedBaseSubscriptionConfiguration'\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ExtendedPreview'\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Subscription\n  /subscription:\n    post:\n      summary: Create a new Subscription\n      operationId: post-subscription\n      description: |-\n        Create a new subscription in NetSuite with the given configuration in request body. New subscriptions will always be created in Draft status and will be activated as follows:\n\n        If the created subscription is a Term Subscription, then the subscription has to go through Quote Generation and Acceptance process before activation.\n\n        If the created subscription is an Evergreen subscription, then it can directly be activated skipping the Quote flow by calling the PATCH /Subscription API.\n      parameters:\n        - schema:\n            type: string\n          in: query\n          name: customerId\n          description: \"Required for non-customer (Admin) token, i.e. Admin creating Subscription on Customer's behalf\"\n      requestBody:\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/CreateSubscriptionConfiguration'\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Subscription'\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Subscription\n  /subscription/startTrial:\n    post:\n      summary: Start Trial Subscription\n      operationId: post-subscription-startTrial\n      description: |-\n        Start trial subscription based on Trial Subscription Config present in Production Integration record. Trial config specifies the Subscription Plan, Items, Quantities and trial duration in number of days to be used in trial subscription.\n\n        A customer is not eligible for a trial subscription if he already has any trial or paid subscription against his customer account in NetSuite.\n      parameters:\n        - schema:\n            type: string\n          in: query\n          name: customerId\n          description: Required for non-customer token\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Subscription'\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Subscription  \n  '/subscription/{subscriptionId}/contractualDocuments':\n    post:\n      summary: Create a contractual document\n      operationId: post-subscription-contractualDocuments\n      description: |-\n        Create a contractual document by uploading a PDF file and attaching it to the existing contractual documents record.\n      parameters:\n        - name: subscriptionId\n          in: path\n          description: The identifier of the target subscription.\n          required: true\n          schema:\n            type: integer\n        - name: customerId\n          in: query\n          description: The customer ID (entity ID). Required only for non-customer (admin) token.\n          schema:\n            type: string\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              properties:\n                type:\n                  $ref: '#/components/schemas/ContractualDocumentTypeEnum'\n                filename:\n                  type: string\n                  description: The filename, including the extension. Only PDF files are supported.\n                contents:\n                  type: string\n                  description: The base64-encoded representation of the file contents.\n              required:\n                - type\n                - filename\n                - contents\n              example:\n                type: 'purchase-order'\n                filename: 'sample.pdf'\n                contents: 'JVBERi0xLjMNCiXi48/T...MjcxNA0KJSVFT0YNCg=='\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: object\n                properties:\n                  contractualDocumentsId:\n                    type: integer\n                    description: The identifier of the contractual documents record related to the target subscription.\n                  fileId:\n                    type: integer\n                    description: The identifier of the uploaded file.\n                required:\n                  - contractualDocumentsId\n                  - fileId\n                example:\n                  contractualDocumentsId: 145482\n                  fileId: 16273973\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n        '500':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Subscription\n  '/subscription/{subscriptionId}/renewalIntent':\n    post:\n      summary: Record latest renewal intent.\n      operationId: post-subscription-renewalIntent\n      description: |-\n        Records the date/time of a renewal intent on a certain subscription (opportunity).\n      parameters:\n        - name: subscriptionId\n          in: path\n          description: The identifier of the target subscription.\n          required: true\n          schema:\n            type: integer\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: object\n                properties:\n                  subscriptionId:\n                    type: integer\n                    description: The identifier of the target subscription.\n                  lastActivity:\n                    type: string\n                    description: The date/time recorded as the last renewal activity (ISO format).\n                required:\n                  - subscriptionId\n                  - lastActivity\n                example:\n                  subscriptionId: 1160600\n                  lastActivity: \"2024-02-08T16:40:33.708Z\"\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n        '500':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Subscription\n  '/subscription/{subscriptionId}/updateRenewalPrimaryContact':\n    patch:\n      summary: Update renewal primary contact\n      operationId: post-subscription-updateRenewalPrimaryContact\n      parameters:\n        - name: subscriptionId\n          in: path\n          description: The identifier of the target subscription.\n          required: true\n          schema:\n            type: integer\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              properties:\n                primaryContact:\n                  $ref: '#/components/schemas/Contact'\n      responses:\n        '200':\n          description: Successful response\n        '400':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Subscription\n  '/subscription/{subscriptionId}/getRenewalPrimaryContact':\n    parameters:\n      - name: subscriptionId\n        in: path\n        required: true\n        schema:\n          type: integer\n    get:\n      summary: Get renewal primary contact\n      operationId: get-subscription-getRenewalPrimaryContact\n      description: |-\n        Get the renewal primary contact for the given subscription.\n      responses:\n        '200':\n          description: Successful response\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Contact'\n        '400':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Subscription\n  '/invoice/{number}/download':\n    parameters:\n      - schema:\n          type: string\n        name: number\n        in: path\n        required: true\n        description: Invoice Number taken from the List Invoices API response.\n    get:\n      summary: Download Invoice document\n      operationId: get-invoice-download\n      description: Download Invoice PDF document in base64 format for the given invoice Id in API Input.\n      responses:\n        '200':\n          description: OK\n          content:\n            application/pdf:\n              schema:\n                type: string\n                format: base64\n              example: base64 string\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Invoices\n  /voiceflow/updateVariables:\n    post:\n      summary: Update Voiceflow variables\n      operationId: post-voiceflow-updateVariables\n      description: Update variables for a specific user in Voiceflow\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              required:\n                - userID\n                - variables\n              properties:\n                userID:\n                  type: string\n                  description: The ID of the user in Voiceflow\n                variables:\n                  type: object\n                  description: The variables to update\n                  additionalProperties: true\n      responses:\n        '200':\n          description: Variables updated successfully\n          content:\n            application/json:\n              schema:\n                type: object\n                properties:\n                  message:\n                    type: string\n        '400':\n          description: Bad request\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '500':\n          description: Internal server error\n          $ref: '#/components/responses/Error'\n      tags:\n        - Voiceflow\n      security:\n        - Token: []\n  /quote:\n    post:\n      summary: Generate a NetSuite Quote\n      operationId: post-quote\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: object\n                properties:\n                  id:\n                    type: number\n                    description: Id of quote created\n                  quoteType:\n                    type: string\n                    enum: ['FullTCs', 'NoTCs', 'Reseller', 'Other']\n                required:\n                  - id\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n      description: 'Create a Quote in NetSuite against a draft term subscription. The Draft subscription can be a new subscription, an upgrade of an active paid or trial subscription or a draft renewal subscription.'\n      tags:\n        - Quote\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              properties:\n                subscriptionId:\n                  type: integer\n                orderType:\n                  type: string\n                  pattern: '^([Rr][Ee][Nn][Ee][Ww][Aa][Ll]|[Qq][Uu][Oo][Tt][Ee])$'\n                recipients:\n                  type: array\n                  items:\n                    type: object\n                    properties:\n                      email:\n                        type: string\n                      role:\n                        type: string\n                        pattern: '^([Cc][Cc]|[Ss][Ii][Gg][Nn][Ee][Rr])$'\n                    required:\n                      - email\n                      - role\n                expiry:\n                  type: string\n                  pattern: '^(\\d{2}-\\w{3}-\\d{4})$'\n                quoteLineStartDates:\n                  type: array\n                  items:\n                    type: object\n                    properties:\n                      line:\n                        type: string\n                      startDate:\n                        type: string\n                    required:\n                      - line\n                      - startDate\n                quoteLineEndDates:\n                  type: array\n                  items:\n                    type: object\n                    properties:\n                      line:\n                        type: string\n                      endDate:\n                        type: string\n                    required:\n                      - line\n                      - endDate\n                salesRep:\n                  type: number\n                lineItemsHeaderText:\n                  type: string\n                lineItemsFooterText:\n                  type: string\n                terms:\n                  type: string\n              required:\n                - subscriptionId\n  /quote/createForSelfServe:\n    post:\n      summary: Create a NetSuite Quote for Self-Serve\n      operationId: post-quote-create-for-self-serve\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: object\n                properties:\n                  id:\n                    type: number\n                    description: Id of quote created\n                required:\n                  - id\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n      description: 'Create a quote soft-linked to a renewal subscription in NetSuite.'\n      tags:\n        - Quote\n      requestBody:\n        content:\n          application/json:\n            schema:\n              allOf:\n                - type: object\n                  properties:\n                    subscriptionId:\n                      type: integer\n                    ccRecipients:\n                      type: array\n                      description: A list of recipients. If defined, this array must contain one and only one signer. If there is no signer, this list will be ignored. If there are more than one signer, an error will be thrown.\n                      items:\n                        type: object\n                        properties:\n                          email:\n                            type: string\n                            description: The email address of the recipient, or an email list separated by comma or semicolon characters.\n                        required:\n                          - email\n                    signer:\n                      $ref: '#/components/schemas/Contact'\n                - $ref: '#/components/schemas/BaseSubscriptionConfiguration'\n              required:\n                - subscriptionId\n                - planCode\n                - items\n                - frequency\n                - duration\n              example:\n                subscriptionId: 10\n                ccRecipients:\n                  - email: first-cc@customer.com\n                  - email: second-cc@customer.com\n                planCode: Kayako TNK GROWTH PLATINUM\n                items:\n                  - code: Kay-SA-TNK-STA\n                    quantity: 25\n                  - code: Kay-SA-COL-STA\n                    quantity: 2\n                frequency: MONTHLY\n                duration: 12\n                signer:\n                  name:\n                    title: Mr\n                    firstName: John\n                    lastName: Doe\n                  email: john.doe@example.com\n                  phone: 1234567890\n  '/quote/{quoteId}/download':\n    parameters:\n      - schema:\n          type: integer\n        name: quoteId\n        in: path\n        required: true\n    get:\n      summary: Download quote PDF\n      tags:\n        - Quote\n      responses:\n        '200':\n          description: OK\n          headers: {}\n          content:\n            application/pdf:\n              schema:\n                type: string\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n      operationId: get-quote-quoteId-download\n      description: |-\n        Download quote PDF in base64 format against the quote id provided in API input.\n\n        The Quote PDF will also contain the Terms and Conditions PDF appended with Quote document. The Terms and Conditions PDF document is taken from Product Integration Record.\n  '/quote/{quoteId}/accept':\n    parameters:\n      - schema:\n          type: integer\n        name: quoteId\n        in: path\n        required: true\n    post:\n      summary: 'Accept quote, save acceptance parameters and email Quote for eSignatures.'\n      operationId: post-quote-quoteId-accept\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: object\n                properties:\n                  id:\n                    type: integer\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n      description: |-\n        Accept quote and record the customer acceptance details (e.g. Acceptor's name, title, email, ccEmail, time of acceptance and IP Address) in a contractual document object in NetSuite. The contractual document also contains the link to accepted quote and conractual document is linked to the subscription through the Contractual Document Field.\n\n        Once the Quote is accepted, an Adobe eSign agreement is also created in NetSuite against the accepted Quote and emailed to Acceptor for eSignatures, and also cc'ed to ccEmail if specified.\n\n        Once the Quote is accepted through API, the related Term Subscription can be activated. The eSignatures through email is an asynchronous operation and does not prevent the subscription from activation.\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              properties:\n                acceptor:\n                  type: object\n                  required:\n                    - name\n                    - jobTitle\n                    - email\n                    - phone\n                  properties:\n                    name:\n                      type: string\n                      minLength: 1\n                      pattern: ^\\S.+\n                    jobTitle:\n                      type: string\n                      pattern: ^\\S.+\n                      minLength: 1\n                    email:\n                      type: string\n                      format: email\n                    phone:\n                      type: string\n                      pattern: ^\\S.+\n                      minLength: 1\n                ccEmail:\n                  type: string\n                  format: email\n                  nullable: true\n              required:\n                - acceptor\n            examples:\n              example-1:\n                value:\n                  acceptor:\n                    name: Tyler\n                    jobTitle: COO\n                    email: tyler@paperstreetsoap.com\n                    phone: (288) 555-0153\n                  ccEmail: thenarrator2@paperstreetsoap.com\n      tags:\n        - Quote\n  '/quote/{quoteId}/poDocument':\n    post:\n      summary: Attach PO Document to Quote\n      operationId: post-quotes-quoteId-poDocument\n      description: Attach a PO document to the quote\n      parameters:\n        - name: quoteId\n          in: path\n          description: The unique identifier of the quote to which the PO document is to be attached.\n          required: true\n          schema:\n            type: string\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              properties:\n                poDocument:\n                  type: string\n                  description: The base64-encoded representation of the file contents. Only PDF files are supported.\n                poNumber:\n                  type: string\n                  description: The purchase order number.\n              required:\n                - poDocument\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: object\n                properties:\n                  poNetsuiteFileId:\n                    type: integer\n                    description: The identifier of the PO document in NetSuite.\n        '400':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n        '500':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Quote\n  /invoice:\n    parameters: []\n    post:\n      summary: Generate a new invoice for a billing account.\n      operationId: post-invoice\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/InvoiceInfo'\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n      description: |-\n        Generate an invoice against a billing account of a customer. This API is intended to be used for new customers who made a first time purchase and have no previous active subscription available. This API would generate an Invoice for the new purchase made and present the customer with a Stripe Invoice Payment link to make the payment.\n\n        The Subscription ID in input would correctly determine the billing account to be used and also specifies the subscription he has just purchased which needs to be invoiced.\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              properties:\n                subscriptionId:\n                  type: integer\n              required:\n                - subscriptionId\n      tags:\n        - Invoices\n  /ui/customer/interests/:\n    post:\n      summary: Enrolls the customer in the interests of specific prime products.\n      description: |\n        The customer will be enrolled in the interests of the prime products specified in the request body.\n        \n        This request works only for a customer context, as the email address is retrieved from the JWT token.\n      tags:\n        - UI customer\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              properties:\n                subscriptionId:\n                  type: integer\n                  description: The active subscription currently undergoing the renewal process (i.e. the parent subscription).\n                productCodes:\n                  type: array\n                  description: A list of prime products.\n                  items:\n                    type: string\n                    description: A prime product code, with case-insensitive matching.\n              required:\n                - subscriptionId\n                - productCodes\n              example:\n                subscriptionId: 1196564\n                productCodes:\n                  - Cloudfix\n                  - Crossover\n      responses:\n        '204':\n          description: Successful response. No content.\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n        '500':\n          $ref: '#/components/responses/Error'\n  /ui/customer/support:\n    post:\n      summary: Submits a customer support request.\n      description: |\n        The customer support request will be submitted to the customer support team.\n\n        This request works only for a customer context, as the email address is retrieved from the JWT token.\n      tags:\n        - UI customer\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              properties:\n                subscriptionId:\n                  type: integer\n                  description: The identifier of the subscription to be renewed.\n                message:\n                  type: string\n                  description: The customer's request message.\n                firstName:\n                  type: string\n                  description: The customer's first name.\n                lastName:\n                  type: string\n                  description: The customer's last name.\n                phone:\n                  type: string\n                  description: The customer's phone number.\n              required:\n                - subscriptionId\n                - message\n              example:\n                subscriptionId: 123456\n                message: \"I need assistance with my subscription.\"\n                firstName: \"John\"\n                lastName: \"Doe\"\n                phone: \"123-456-7890\"\n      responses:\n        '204':\n          description: Successful response. No content.\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n        '500':\n          $ref: '#/components/responses/Error'\n  /ui/storage:\n    get:\n      summary: Get the content stored for a given subscription in the user context.\n      tags:\n        - UI storage\n      parameters:\n        - name: subscriptionId\n          in: query\n          required: true\n          schema:\n            type: string\n            description: The identifier of the subscription.\n      responses:\n        '200':\n          description: Successful response.\n          content:\n            application/json:\n              schema:\n                type: object\n                description: The JSON content stored. The default value is null.\n                additionalProperties: {}\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '500':\n          $ref: '#/components/responses/Error'\n    put:\n      summary: Update the content stored for a given subscription in the user context.\n      tags:\n        - UI storage\n      parameters:\n        - name: subscriptionId\n          in: query\n          required: true\n          schema:\n            type: string\n            description: The identifier of the subscription.\n      requestBody:\n        required: true\n        content:\n          application/json:\n            schema:\n              type: object\n              description: The JSON content to store.\n              additionalProperties: {}\n      responses:\n        '204':\n          description: Content updated successfully.\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '500':\n          $ref: '#/components/responses/Error'\n  '/ui/subscription/{subscriptionId}/agreementStatus':\n    parameters:\n      - schema:\n          type: integer\n        name: subscriptionId\n        in: path\n        required: true\n    get:\n      summary: Get the most advanced agreement status of Self-Serve quotes for the given subscription.\n      tags:\n        - UI subscription\n      responses:\n        '200':\n          description: Successful response.\n          content:\n            text/plain:\n              schema:\n                $ref: '#/components/schemas/AgreementStatusResponseEnum'\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n        '500':\n          $ref: '#/components/responses/Error'\ncomponents:\n  schemas:\n    CustomerInfo:\n      type: object\n      description: Short customer info to match. If customer is company - companyName will be not empty\n      example:\n        id: '4651565415'\n        firstName: John\n        lastName: Smith\n        email: john.smith@example.com\n        companyName: Smith tools\n        taxIdentificationNumber: ABCDF1234J\n        address:\n          line1: 536 Paper street\n          line2: 2nd floor\n          city: Bradford\n          state: DE\n          country: US\n          zip: '19808'\n          phone: 111-111-111\n        shippingAddress:\n          line1: 17 Sheet street\n          line2: 3rd floor\n          city: Texas City\n          state: TX\n          country: US\n          zip: '12345'\n          phone: 222-222-222\n        primaryContact:\n          name:\n            title: Mr\n            firstName: Tyler\n            middleName: E\n            lastName: Durden\n          email: tyler@paperstreetsoap.com\n          phone: (288) 555-0153\n          billingAddress:\n            line1: 536 Paper street\n            line2: 2nd floor\n            city: Bradford\n            state: DE\n            country: US\n            zip: '19808'\n            phone: 111-111-111\n      x-examples:\n        example-1:\n          id: '4651565415'\n          firstName: John\n          lastName: Smith\n          email: john.smith@example.com\n          companyName: Smith tools\n          taxIdentificationNumber: ABCDF1234K\n          address:\n            line1: 536 Paper street\n            line2: 2nd floor\n            city: Bradford\n            state: DE\n            country: US\n            zip: '19808'\n            phone: 111-111-111\n          shippingAddress:\n            line1: 17 Sheet street\n            line2: 3rd floor\n            city: Texas City\n            state: TX\n            country: US\n            zip: '12345'\n            phone: 222-222-222\n          primaryContact:\n            name:\n              title: Mr\n              firstName: Tyler\n              middleName: E\n              lastName: Durden\n            email: tyler@paperstreetsoap.com\n            phone: (288) 555-0153\n            billingAddress:\n              line1: 536 Paper street\n              line2: 2nd floor\n              city: Bradford\n              state: DE\n              country: US\n              zip: '19808'\n              phone: 111-111-111\n      properties:\n        id:\n          type: string\n        firstName:\n          type: string\n          maxLength: 32\n        lastName:\n          type: string\n          maxLength: 32\n        email:\n          type: string\n          format: email\n        phone:\n          type: string\n        companyName:\n          type: string\n        taxIdentificationNumber:\n          type: string\n          description: The tax identification number of the customer.\n          example: ABCDF1234J\n          nullable: true\n        address:\n          description: The billing address, and if not defined separately, the shipping address.\n          allOf:\n            - $ref: '#/components/schemas/Address'\n        shippingAddress:\n          description: The shipping address, if different from the billing address.\n          allOf:\n            - $ref: '#/components/schemas/Address'\n        primaryContact:\n          $ref: '#/components/schemas/Contact'\n    Subscription:\n      type: object\n      example:\n        id: 487524\n        status: DRAFT\n        currency: USD\n        customer:\n          id: '4651565415'\n          firstName: John\n          lastName: Smith\n          email: john.smith@example.com\n          phone: '1234567'\n          companyName: Smith tools\n          taxIdentificationNumber: ABCDF1234J\n          address:\n            line1: 536 Paper street\n            line2: 2nd floor\n            city: Bradford\n            state: DE\n            country: US\n            zip: '19808'\n            phone: 111-111-111\n          shippingAddress:\n            line1: 17 Sheet street\n            line2: 3rd floor\n            city: Texas City\n            state: TX\n            country: US\n            zip: '12345'\n            phone: 222-222-222\n        endUser:\n          id: '4651565415'\n          firstName: John\n          lastName: Smith\n          email: john.smith@example.com\n          phone: '1234567'\n          companyName: Smith tools\n          taxIdentificationNumber: ABCDF1234L\n          address:\n            line1: 536 Paper street\n            line2: 2nd floor\n            city: Bradford\n            state: DE\n            country: US\n            zip: '19808'\n            phone: 111-111-111\n          shippingAddress:\n            line1: 17 Sheet street\n            line2: 3rd floor\n            city: Texas City\n            state: TX\n            country: US\n            zip: '12345'\n            phone: 222-222-222\n        serialOrLicenseNumber: 112233\n        plan:\n          id: 85156\n          code: Kay-SA-TNK-STA-PLA\n          description: Kayako TNK Growth, Platinum Success\n          title: Kayako TNK GROWTH PLATINUM\n          productTier: Standard\n          productTierTitle: Standard\n          supportLevel: Platinum\n          revenueType: SaaS\n          isTrial: false\n        items:\n          - id: 82865\n            code: Kay-SA-TNK-STA\n            title: Kayako TNK Standard\n            type: Recurring\n            typeId: 2\n            desc: description\n            minQuantity: 1\n            maxQuantity: 10000\n            required: true\n            prices:\n              - type: Tiered\n                frequency: ANNUALLY\n                pricebookid: 10611\n                ranges:\n                  - priceplanid: 4889293\n                    type: Rate\n                    fromQuantity: 0\n                    price: 10\n                  - priceplanid: 4889293\n                    type: Rate\n                    fromQuantity: 1000\n                    price: 9\n              - type: Tiered\n                frequency: MONTHLY\n                ranges:\n                  - fromQuantity: 0\n                    price: 11\n                  - fromQuantity: 1000\n                    price: 10\n            amount: 50\n            totalIntervalValue: 40\n            productTier: Standard\n            revenueType: SaaS\n        includedItems:\n          - id: 82865\n            code: Kay-SA-TNK-STA\n            quantity: 5\n        term:\n          start: 1-Nov-2021\n          end: 31-Oct-2022\n          frequency: ANNUALLY\n          nextBillCycleDate: 1-Dec-2021\n        autorenewal: false\n        parentSubscription: 545457\n        renewalNumber: 2\n        totalAmount: 50\n        totalIntervalValue: 40\n        operations:\n          ['renew', 'changeEdition', 'changeSuccessPlan', 'changeQuantity', 'changeTerm', 'changeBillingFrequency']\n        quotes:\n          - id: 36891513\n            isSelfServe: true\n            quoteNumber: 123\n            createddate: '2022-01-01 00:00:00'\n            status: Draft\n            productTier: Standard\n            successLevel: Platinum\n            duration: 12\n            averageARR: 100\n            totalIntervalValue: 1000\n            agreements:\n              - id: 204502\n                type: 'Quote'\n                status: 'Draft'\n              - id: 204503\n                type: 'End User Agreement'\n                status: 'Draft'\n          - id: 36891514\n            isSelfServe: false\n            quoteNumber: 1234\n            createddate: '2022-02-01 00:00:00'\n            status: Draft\n            productTier: Standard\n            successLevel: Platinum\n            duration: 12\n            averageARR: 100\n            totalIntervalValue: 1000\n            agreements:\n              - id: 204504\n                type: 'Quote'\n                status: 'Out For Signature'\n          - id: 36891515\n            isSelfServe: false\n            quoteNumber: 1235\n            createddate: '2022-03-01 00:00:00'\n            status: Draft\n            productTier: Standard\n            successLevel: Platinum\n            duration: 12\n            averageARR: 100\n            totalIntervalValue: 1000\n            agreements: []\n        excludeFromSelfServe: false\n        isPrime: false\n        priceReset: false\n        renewalPrimaryContact:\n          $ref: '#/components/schemas/Contact'\n        operationDenialReasons:\n          renew: 'Subscription end date is not close enough'\n      properties:\n        id:\n          type: number\n          readOnly: true\n        status:\n          $ref: '#/components/schemas/StatusEnum'\n        currency:\n          type: string\n          maxLength: 3\n          minLength: 3\n          description: ISO currency code\n        customer:\n          $ref: '#/components/schemas/CustomerInfo'\n        distributor:\n          $ref: '#/components/schemas/CustomerInfo'\n        reseller:\n          $ref: '#/components/schemas/CustomerInfo'\n        enduser:\n          $ref: '#/components/schemas/CustomerInfo'\n        serialOrLicenseNumber:\n          type: string\n        plan:\n          $ref: '#/components/schemas/SubscriptionPlanInfo'\n        items:\n          type: array\n          items:\n            allOf:\n              - $ref: '#/components/schemas/SubscriptionLineItem'\n              - type: object\n                properties:\n                  amount:\n                    type: number\n        includedItems:\n          type: array\n          items:\n            type: object\n            properties:\n              id:\n                type: number\n              code:\n                type: string\n              quantity:\n                type: number\n            required:\n              - code\n        term:\n          type: object\n          required:\n            - start\n            - frequency\n          properties:\n            start:\n              type: string\n            end:\n              type: string\n            frequency:\n              $ref: '#/components/schemas/FrequencyEnum'\n            nextBillCycleDate:\n              type: string\n        autorenewal:\n          type: boolean\n        parentSubscriptionId:\n          type: number\n          description: ID of previous subscription (active or not) if this subscription is renewal\n        renewalNumber:\n          type: number\n          description: Renewal cycle number\n        totalAmount:\n          type: number\n        totalIntervalValue:\n          type: number\n        operations:\n          type: array\n          items:\n            type: string\n            pattern: '^(renew|changeEdition|changeSuccessPlan|changeQuantity|changeTerm|changeBillingFrequency)$'\n        quotes:\n          type: array\n          items:\n            $ref: '#/components/schemas/Quote'\n        excludeFromSelfServe:\n          type: boolean\n        isPrime:\n          type: boolean\n        priceReset:\n          type: boolean\n        renewalPrimaryContact:\n          $ref: '#/components/schemas/Contact'\n        operationDenialReasons:\n          type: object\n          properties:\n            renew:\n              type: string\n              enum:\n                - 'Subscription end date is not close enough'\n                - 'Subscription is excluded from self serve'\n                - 'Subscription is prime'\n                - 'Subscription sold through Reseller or Distributor, end user can’t renew'\n                - 'Subscription has a pending activation'\n                - 'Subscription is of $0'\n                - 'Product is not enabled for Self-Serve'\n                - 'Subscription has no draft renewal'\n                - 'Subscription is not active'\n                - 'The related draft subscription was terminated'\n              description: |\n                Reason for denying the renewal operation. Possible values:\n                - 'Subscription end date is not close enough': The subscription's end date is too far in the future to allow renewal (e.g., there are more than 220 days until the end date).\n                - 'Subscription is excluded from self serve': The subscription has been manually excluded from renewing via the Self-Serve Portal by checking the 'Exclude from Self-Serve' checkbox on the subscription page.\n                - 'Subscription is prime': Prime subscriptions are complementary free licenses when buying a different product. They require special handling and cannot be renewed through the Self-Serve Portal. A Prime subscription is identified by the 'Prime' checkbox on the subscription page.\n                - 'Subscription sold through Reseller or Distributor, end user can't renew': End users cannot renew subscriptions sold through partners. Such a subscription has a different 'End User' attribute than the 'Customer.'\n                - 'Subscription has a pending activation': The active parent subscription already has a child subscription in 'Pending Activation' status. The renewal process is almost finished; the only thing remaining is for the child subscription to go into 'Active' status and for the parent to get into 'Closed' status.\n                - 'Subscription is of $0': Free subscriptions cannot be renewed through the Self-Serve Portal. The $0 results from analyzing the Total Interval Value at the item Lines & Pricing level (not the ARR at the subscription level).\n                - 'Product is not enabled for Self-Serve': The 'Self-Serve' checkbox is not checked in the product's Class record associated with this subscription (via the subscription's Class attribute, not the subscription plan's Class).\n                - 'Subscription has no draft renewal': A related child subscription must exist in Draft status before the renewal process can begin.\n                - 'Subscription is not active': Only active subscriptions can be renewed.\n                - 'The related draft subscription was terminated': The draft child subscription has been terminated (at the items level), preventing renewal.\n          description: \"Detailed reasons for each operation that was denied, keyed by operation type.\"\n      required:\n        - id\n        - status\n        - plan\n        - term\n        - items\n        - includedItems\n        - excludeFromSelfServe\n        - priceReset\n      x-examples:\n        example-1:\n          id: 487524\n          status: ACTIVE\n          currency: USD\n          customer:\n            id: '4651565415'\n            firstName: John\n            lastName: Smith\n            email: john.smith@example.com\n            company: Smith tools\n          enduser:\n            id: '4651565415'\n            firstName: John\n            lastName: Smith\n            email: john.smith@example.com\n            company: Smith tools\n          serialOrLicenseNumber: 112233\n          plan:\n            id: 82902\n            code: Premium Plan\n            description: Premium Plan description\n            title: The Premium Plan\n            productTier: Standard\n            supportLevel: Silver\n            revenueType: SaaS\n            isTrial: false\n          items:\n            - id: 82865\n              code: DNN-SA-CUS-BA\n              title: item title\n              type: Recurring\n              desc: description\n              minQuantity: 1\n              maxQuantity: 10000\n              required: true\n              prices:\n                - type: Tiered\n                  frequency: ANNUALLY\n\n                  ranges:\n                    - fromQuantity: 0\n                      price: 10\n                    - fromQuantity: 1000\n                      price: 9\n                - type: Tiered\n                  frequency: MONTHLY\n                  ranges:\n                    - fromQuantity: 0\n                      price: 11\n                    - fromQuantity: 1000\n                      price: 10\n              amount: 50\n          includedItems:\n            - id: 82865\n              code: DNN-SA-CUS-BA\n              quantity: 5\n          term:\n            start: 1-NOV-2021\n            end: 31-OCT-2022\n            frequency: ANNUALLY\n          autorenewal: false\n          parentSubscription: 545457\n          renewalNumber: 2\n          totalAmount: 50\n          excludeFromSelfServe: false\n          isPrime: false\n          priceReset: false\n      description: |-\n        Subscription view model.\n        Pricing and amounts will hidden if current user is not customer.\n    Quote:\n      description: |-\n        Quote view model.\n      type: object\n      properties:\n        id:\n          type: number\n          readOnly: true\n        isSelfServe:\n          type: boolean\n          readOnly: true\n          description: Whether the quote is a self-serve quote or not.\n        quoteNumber:\n          type: integer\n        createddate:\n          type: string\n          format: date-time\n        status:\n          type: string\n        productTier:\n          type: string\n        successLevel:\n          type: string\n        duration:\n          type: integer\n          description: Term duration in months\n        averageARR:\n          type: number\n        totalIntervalValue:\n          type: number  \n        agreements:\n          type: array\n          items:\n            $ref: '#/components/schemas/Agreement'\n      required:\n        - id\n        - isSelfServe\n        - quoteNumber\n        - createddate\n        - status\n        - duration\n        - averageARR\n        - totalIntervalValue\n    Agreement:\n      description: |-\n        Agreement view model.\n      type: object\n      properties:\n        id:\n          type: number\n          readOnly: true\n        type:\n          $ref: '#/components/schemas/AgreementTypeEnum'\n        status:\n          $ref: '#/components/schemas/AgreementStatusEnum'\n      required:\n        - id\n        - status\n    ProductIntegration:\n      type: object\n      properties:\n        family:\n          $ref: '#/components/schemas/CodeAndTitle'\n        variant:\n          $ref: '#/components/schemas/CodeAndTitle'\n        notification:\n          $ref: '#/components/schemas/UrlAndAuth'\n        secret:\n          type: string\n      example:\n        family:\n          code: SOC\n          title: Sococo\n        variant:\n          code: SA\n          title: SaaS\n        notification:\n          url: 'https://app.sococo.com/sievent'\n          auth:\n            username: eventuser\n            password: eventpassword\n        secret: lrfer2jvf3\n    Event:\n      title: Event\n      type: object\n      description: |-\n        Body structure to be sent to webhook. \n\n        **content** structure depends on **type**. For **type**=\"subscription_X\" it will be SubscriptionInfo\n      x-examples:\n        example-1:\n          type: subscription_created\n          content:\n            id: 487524\n            status: ACTIVE\n            currency: USD\n            customer:\n              id: '4651565415'\n              firstName: John\n              lastName: Smith\n              email: john.smith@example.com\n              company: Smith tools\n            enduser:\n              id: '4651565415'\n              firstName: John\n              lastName: Smith\n              email: john.smith@example.com\n              company: Smith tools\n            plan:\n              id: 82902\n              code: Premium Plan\n              title: The Premium Plan\n              productTier: Standard\n              supportLevel: Silver\n              revenueType: SaaS\n              isTrial: false\n            items:\n              - id: 82865\n                code: DNN-SA-CUS-BA\n                title: item title\n                type: Recurring\n                desc: description\n                minQuantity: 1\n                maxQuantity: 10000\n                required: true\n                prices:\n                  - type: Tiered\n                    frequency: ANNUALLY\n                    ranges:\n                      - fromQuantity: 0\n                        price: 10\n                      - fromQuantity: 1000\n                        price: 9\n                  - type: Tiered\n                    frequency: MONTHLY\n                    ranges:\n                      - fromQuantity: 0\n                        price: 11\n                      - fromQuantity: 1000\n                        price: 10\n                amount: 50\n            includedItems:\n              - id: 82865\n                code: DNN-SA-CUS-BA\n                quantity: 5\n            term:\n              start: 1-NOV-2021\n              end: 31-OCT-2022\n              frequency: ANNUALLY\n            autorenewal: false\n            parentSubscription: 545457\n            renewalNumber: 2\n            totalAmount: 50\n          date: '2019-08-24'\n      properties:\n        type:\n          type: string\n          enum:\n            - subscription_created\n            - subscription_updated\n            - subscription_terminated\n          description: Event type\n        content:\n          $ref: '#/components/schemas/Subscription'\n        date:\n          type: string\n          format: date\n          description: Date when event happened\n      required:\n        - type\n        - content\n        - date\n    SubscriptionItem:\n      title: SubscriptionItem\n      type: object\n      x-examples:\n        example-1:\n          id: string\n          code: string\n          title: string\n          quantity: 2\n          status: ACTIVE\n          type: onetime\n      properties:\n        id:\n          type: number\n        code:\n          type: string\n        title:\n          type: string\n        quantity:\n          type: number\n        status:\n          type: string\n          enum:\n            - ACTIVE\n            - PENDING_ACTIVATION\n            - SUSPENDED\n            - DRAFT\n            - CLOSED\n            - TERMINATED\n            - NOT_INCLUDED\n        type:\n          type: string\n          enum:\n            - onetime\n            - requrring\n            - usage\n      required:\n        - code\n        - quantity\n        - status\n        - type\n    SubscriptionPlanInfo:\n      type: object\n      title: SubscriptionPlanInfo\n      properties:\n        id:\n          type: number\n        code:\n          type: string\n        description:\n          type: string\n          description: Description of the subscription plan\n        title:\n          type: string\n          description: Subscription plan name\n        productTier:\n          $ref: '#/components/schemas/ProductTierEnum'\n        productTierTitle:\n          type: string\n        supportLevel:\n          $ref: '#/components/schemas/SupportLevelEnum'\n        revenueType:\n          type: string\n        isTrial:\n          type: boolean\n      required:\n        - id\n        - code\n    SubscriptionPlan:\n      title: SubscriptionPlan\n      type: object\n      x-examples:\n        example-Sococo-Unlimited:\n          id: '123'\n          code: SOC-SUB-UNLIMITED\n          _ns_displayname: SOC-SUB-UNLIMITED\n          description: Sococo Unlimited\n          title: Sococo Unlimited\n          isTrial: false\n          product:\n            family:\n              code: SOC\n              title: SOC\n            variant:\n              code: SA\n              title: SaaS\n          initialterm:\n            name: Annual - 1 Year\n            unit: MONTHS\n            duration: 12\n            type: STANDARD\n          items:\n            - id: '123'\n              code: SOC-SUBI-USERS\n              title: Users\n              type: required\n              desc: Number of seats\n              maxQuantity: 999999\n              minQuantity: 10\n              prices:\n                - type: tiered\n                  frequency: monthly\n                  ranges:\n                    - fromQuantity: 0\n                      price: 42\n                  currency: USD\n            - id: '123'\n              code: SOC-SUBI-MEDIA-PKG\n              title: Media minutes\n              type: addon\n              desc: 1000 minutes\n              maxQuantity: 999999\n              minQuantity: 0\n              prices:\n                - type: tiered\n                  frequency: monthly\n                  ranges:\n                    - fromQuantity: 0\n                      price: 13\n                  currency: USD\n        example-Sococo-Standard:\n          id: '234'\n          code: SOC-SUB-STD\n          _ns_displayname: SOC-SUB-STD\n          description: Sococo\n          title: Sococo\n          isTrial: false\n          product:\n            family:\n              code: SOC\n              title: SOC\n            variant:\n              code: SA\n              title: SaaS\n          initialterm:\n            name: Annual - 1 Year\n            unit: MONTHS\n            duration: 12\n            type: STANDARD\n          items:\n            - id: '123'\n              code: SOC-SUBI-USERS\n              title: Users\n              type: required\n              desc: Number of seats\n              maxQuantity: 999999\n              minQuantity: 10\n              prices:\n                - type: tiered\n                  frequency: monthly\n                  ranges:\n                    - fromQuantity: 0\n                      price: 68\n                  currency: USD\n            - id: '123'\n              code: SOC-SUBI-MEDIA-PKG\n              title: Media minutes\n              type: addon\n              desc: 1000 minutes\n              maxQuantity: 999999\n              minQuantity: 0\n              prices:\n                - type: tiered\n                  frequency: monthly\n                  ranges:\n                    - fromQuantity: 0\n                      price: 13\n                  currency: USD\n          productTier: Standard\n          supportLevel: Silver\n          revenueType: SaaS\n      properties:\n        id:\n          type: number\n          description: Internal plan id\n        code:\n          type: string\n          description: Code to identify plan on product side. Corresponds to subscription plan name\n        _ns_displayname:\n          type: string\n          description: Plan display name in english\n        description:\n          type: string\n          description: Description of the subscription plan\n        title:\n          type: string\n          description: Description of the subscription plan (deprecated)\n        isTrial:\n          type: boolean\n          description: Indicate if subscription plan is for trial\n        product:\n          $ref: '#/components/schemas/ProductCoordinates'\n        initialterm:\n          $ref: '#/components/schemas/TermDescription'\n        items:\n          type: array\n          items:\n            $ref: '#/components/schemas/SubscriptionPlanItem'\n        productTier:\n          $ref: '#/components/schemas/ProductTierEnum'\n        productTierTitle:\n          type: string\n        supportLevel:\n          $ref: '#/components/schemas/SupportLevelEnum'\n        revenueType:\n          type: string\n        supportOnly:\n          type: boolean\n          description: Indicate tha this plan is support only and can be upgraded only to another support only plan\n      required:\n        - code\n        - items\n    TermDescription:\n      title: TermDescription\n      type: object\n      properties:\n        name:\n          type: string\n        unit:\n          $ref: '#/components/schemas/UnitTermEnum'\n        duration:\n          type: number\n        type:\n          $ref: '#/components/schemas/TermTypeEnum'\n      example:\n        name: Annual - 1 Year\n        unit: MONTHS\n        duration: 12\n        type: STANDARD\n    ProductCoordinates:\n      title: ProductCoordinates\n      type: object\n      properties:\n        family:\n          $ref: '#/components/schemas/CodeAndTitle'\n        variant:\n          $ref: '#/components/schemas/CodeAndTitle'\n      example:\n        family:\n          code: SOC\n          title: Sococo\n        variant:\n          code: SA\n          title: 'SaaS, the only one, just default'\n    CodeAndTitle:\n      title: ElementPair\n      type: object\n      properties:\n        code:\n          type: string\n          description: Code to be used for identification\n        title:\n          type: string\n          description: Displayable entity title\n    JWTToken:\n      title: JWTToken\n      type: object\n      properties:\n        pfc:\n          type: string\n          description: Product family code\n        pvc:\n          type: string\n          description: Product variant code\n        cid:\n          type: string\n          description: Customer ID\n        padm:\n          type: boolean\n          description: Product Admin flag. Requred for certain endpoints which must be used only by product backend\n        email:\n          type: string\n          description: Self Serve User Email\n    UrlAndAuth:\n      title: UrlAndAuth\n      type: object\n      properties:\n        url:\n          type: string\n        auth:\n          type: object\n          properties:\n            username:\n              type: string\n            password:\n              type: string\n    InvoiceInfo:\n      title: InvoiceInfo\n      type: object\n      example:\n        stripeInvoicePaymentLink: 'https://app.suitesync.io/payments/acct_1KMEYNArxAm3Gt9Z/custinvc/22035055'\n        number: INV9842454\n        date: 13-Jul-2021\n        dueDate: 12-Aug-2021\n        status:\n          code: A\n          title: 'Invoice:Open'\n        totalAmount: 123.52\n        taxAmount: 12.21\n        currency: USD\n        _asofdate: 1-Jul-2020\n        _id: 5846511\n      properties:\n        stripeInvoicePaymentLink:\n          type: string\n        number:\n          type: string\n        date:\n          type: string\n        dueDate:\n          type: string\n        totalAmount:\n          type: number\n        taxAmount:\n          type: number\n        currency:\n          type: string\n        status:\n          $ref: '#/components/schemas/CodeAndTitle'\n        _asofdate:\n          type: string\n        _id:\n          type: integer\n      required:\n        - number\n        - date\n        - dueDate\n        - totalAmount\n        - taxAmount\n        - currency\n        - status\n    Address:\n      title: Address\n      type: object\n      example:\n        line1: 536 Paper street\n        line2: ''\n        city: Bradford\n        state: DE\n        country: US\n        zip: '19808'\n        phone: 111-111-111\n      x-examples:\n        example-1:\n          line1: 536 Paper street\n          line2: ''\n          city: Bradford\n          state: DE\n          country: US\n          zip: '19808'\n          phone: 111-111-111\n      nullable: true\n      properties:\n        line1:\n          type: string\n          nullable: true\n        line2:\n          type: string\n          nullable: true\n        city:\n          type: string\n          nullable: true\n        state:\n          type: string\n          nullable: true\n        country:\n          type: string\n          nullable: true\n        zip:\n          type: string\n          nullable: true\n        phone:\n          type: string\n          nullable: true\n    Customer:\n      title: Customer\n      type: object\n      x-internal: false\n      example:\n        id: SOC-SA-6048b1177cd71936d2234cc6\n        individual: false\n        stripeCustomerAccountLink: 'https://app.suitesync.io/customers/acct_1KMEyNArTAm3Gt1Z/537215/0611239180'\n        individualName:\n          title: Mr\n          firstName: Tyler\n          middleName: E\n          lastName: Durden\n        companyName: Paper Street Soap Co.\n        currency: USD\n        email: tyler@paperstreetsoap.com\n        phone: (288) 555-0153\n        taxIdentificationNumber: ABCDF1234J\n        address:\n          line1: 536 Paper street\n          line2: 2nd floor\n          city: Bradford\n          state: DE\n          country: US\n          zip: '19808'\n          phone: 111-111-111\n        shippingAddress:\n          line1: 17 Sheet street\n          line2: 3rd floor\n          city: Texas City\n          state: TX\n          country: US\n          zip: '12345'\n          phone: 222-222-222\n        primaryContact:\n          name:\n            title: Mr\n            firstName: Tyler\n            middleName: E\n            lastName: Durden\n          email: tyler@paperstreetsoap.com\n          phone: (288) 555-0153\n          billingAddress:\n            line1: 536 Paper street\n            line2: 2nd floor\n            city: Bradford\n            state: DE\n            country: US\n            zip: '19808'\n            phone: 111-111-111\n      x-examples:\n        example-1:\n          id: SOC-SA-6048b1177cd71936d2234cc6\n          individual: false\n          individualName:\n            title: Mr\n            firstName: Tyler\n            middleName: E\n            lastName: Durden\n          companyName: Paper Street Soap Co.\n          currency: USD\n          email: tyler@paperstreetsoap.com\n          phone: (288) 555-0153\n          taxIdentificationNumber: ABCDF1234K\n          address:\n            line1: 536 Paper street\n            line2: 2nd floor\n            city: Bradford\n            state: DE\n            country: US\n            zip: '19808'\n            phone: 111-111-111\n          primaryContact:\n            name:\n              title: Mr\n              firstName: Tyler\n              middleName: E\n              lastName: Durden\n            email: tyler@paperstreetsoap.com\n            phone: (288) 555-0153\n            billingAddress:\n              line1: 536 Paper street\n              line2: 2nd floor\n              city: Bradford\n              state: DE\n              country: US\n              zip: '19808'\n              phone: 111-111-111\n      properties:\n        id:\n          type: string\n          maxLength: 83\n          nullable: true\n        stripeCustomerAccountLink:\n          type: string\n        individual:\n          type: boolean\n          description: 'true for person, false for company'\n          nullable: true\n        individualName:\n          $ref: '#/components/schemas/PersonName'\n        companyName:\n          type: string\n          maxLength: 83\n          description: Required if customer is company\n          nullable: true\n        currency:\n          type: string\n          maxLength: 3\n          minLength: 3\n          description: ISO currency code\n          nullable: true\n        email:\n          type: string\n          format: email\n          maxLength: 254\n          nullable: true\n        phone:\n          type: string\n          maxLength: 32\n          nullable: true\n        taxIdentificationNumber:\n          type: string\n          nullable: true\n        address:\n          description: The billing address, and if not defined separately, the shipping address.\n          allOf:\n            - $ref: '#/components/schemas/Address'\n        shippingAddress:\n          description: The shipping address, if different from the billing address.\n          allOf:\n            - $ref: '#/components/schemas/Address'\n        primaryContact:\n          $ref: '#/components/schemas/Contact'\n    Contact:\n      title: Contact\n      type: object\n      example:\n        id: '321'\n        email: tyler@paperstreetsoap.com\n        title: Mr\n        firstName: Tyler\n        middleName: ''\n        lastName: Durden\n        phone: (288) 555-0153\n        billingAddress:\n          line1: 536 Paper street\n          line2: ''\n          city: Bradford\n          state: DE\n          country: US\n          zip: '19808'\n          phone: 111-111-111\n      nullable: true\n      properties:\n        id:\n          type: string\n          nullable: true\n        name:\n          $ref: '#/components/schemas/PersonName'\n        email:\n          type: string\n          format: email\n          maxLength: 254\n          nullable: true\n        phone:\n          type: string\n          maxLength: 32\n          nullable: true\n        billingAddress:\n          $ref: '#/components/schemas/Address'\n    BaseSubscriptionConfiguration:\n      title: BaseSubscriptionConfiguration\n      type: object\n      description: 'Set of items, quantities and plan for subscription creation and modification'\n      example:\n        planCode: Kayako TNK GROWTH PLATINUM\n        items:\n          - code: Kay-SA-TNK-STA\n            quantity: 25\n          - code: Kay-SA-COL-STA\n            quantity: 2\n        frequency: MONTHLY\n        duration: 12\n      properties:\n        planCode:\n          type: string\n        items:\n          type: array\n          items:\n            type: object\n            properties:\n              code:\n                type: string\n              quantity:\n                type: integer\n            required:\n              - code\n        frequency:\n          $ref: '#/components/schemas/FrequencyEnum'\n        duration:\n          type: integer\n          description: |-\n            Term duration in months. Must be equal or greater than the subscription plan initial term.\n\n            Inform only for creation and renewal. If duration is not informed, the subscription plan initial term will be applied.\n\n            In an update for an active subscription, duration can't be informed.\n          minimum: 1\n          maximum: 84\n    ExtendedBaseSubscriptionConfiguration:\n      allOf:\n        - $ref: '#/components/schemas/BaseSubscriptionConfiguration'\n        - type: object\n          properties:\n            pricingTest:\n              type: boolean\n              description: |-\n                Indicates whether to return the pricing validation information and when it used always return the prices, even if the validation failed.\n                Only possible to be used by super admin.\n      example:\n        planCode: Kayako TNK GROWTH PLATINUM\n        items:\n          - code: Kay-SA-TNK-STA\n            quantity: 25\n          - code: Kay-SA-COL-STA\n            quantity: 2\n        frequency: MONTHLY\n        duration: 12\n        pricingTest: true\n    PersonName:\n      title: PersonName\n      type: object\n      nullable: true\n      properties:\n        title:\n          type: string\n          maxLength: 99\n          nullable: true\n        firstName:\n          type: string\n          maxLength: 32\n          nullable: true\n        middleName:\n          type: string\n          maxLength: 32\n          nullable: true\n        lastName:\n          type: string\n          maxLength: 32\n          nullable: true\n    SubscriptionPlanItem:\n      title: SubscriptionPlanItem\n      type: object\n      properties:\n        id:\n          type: number\n        code:\n          type: string\n        title:\n          type: string\n        type:\n          $ref: '#/components/schemas/ItemTypeEnum'\n        desc:\n          type: string\n        minQuantity:\n          type: integer\n        maxQuantity:\n          type: integer\n          exclusiveMinimum: false\n        required:\n          type: boolean\n        prices:\n          type: array\n          description: Array of prices for frequency\n          items:\n            type: object\n            properties:\n              type:\n                $ref: '#/components/schemas/PriceTypeEnum'\n              frequency:\n                $ref: '#/components/schemas/PriceFrequencyEnum'\n              currency:\n                type: string\n                description: USD by default\n              ranges:\n                type: array\n                items:\n                  type: object\n                  properties:\n                    fromQuantity:\n                      type: integer\n                    price:\n                      type: number\n                  required:\n                    - fromQuantity\n                    - price\n            required:\n              - type\n              - ranges\n        amount:\n          type: number\n        totalIntervalValue:\n          type: number\n      required:\n        - code\n        - type\n    SubscriptionLineItem:\n      title: SubscriptionLineItem\n      type: object\n      properties:\n        id:\n          type: number\n        code:\n          type: string\n        title:\n          type: string\n        type:\n          $ref: '#/components/schemas/ItemTypeEnum'\n        desc:\n          type: string\n        minQuantity:\n          type: integer\n        maxQuantity:\n          type: integer\n          exclusiveMinimum: false\n        required:\n          type: boolean\n        prices:\n          type: array\n          description: Array of prices for frequency\n          items:\n            type: object\n            properties:\n              type:\n                $ref: '#/components/schemas/PriceTypeEnum'\n              frequency:\n                $ref: '#/components/schemas/PriceFrequencyEnum'\n              ranges:\n                type: array\n                items:\n                  type: object\n                  properties:\n                    fromQuantity:\n                      type: integer\n                    price:\n                      type: number\n                  required:\n                    - fromQuantity\n                    - price\n            required:\n              - type\n              - ranges\n        amount:\n          type: number\n        totalIntervalValue:\n          type: number\n      required:\n        - code\n        - type\n    StatusEnum:\n      type: string\n      title: StatusEnum\n      enum:\n        - ACTIVE\n        - PENDING_ACTIVATION\n        - SUSPENDED\n        - DRAFT\n        - CLOSED\n        - TERMINATED\n        - NOT_INCLUDED\n    UnitTermEnum:\n      type: string\n      title: UnitTermEnum\n      enum:\n        - DAYS\n        - WEEKS\n        - MONTHS\n        - YEARS\n    TermTypeEnum:\n      type: string\n      title: TermTypeEnum\n      enum:\n        - CUSTOM\n        - EVERGREEN\n        - STANDARD\n    ProductTierEnum:\n      type: string\n      title: ProductTierEnum\n      enum:\n        - Standard\n        - Professional\n        - Enterprise\n    SupportLevelEnum:\n      type: string\n      title: SupportLevelEnum\n      enum:\n        - Silver\n        - Gold\n        - Platinum\n    ItemTypeEnum:\n      type: string\n      title: ItemTypeEnum\n      enum:\n        - One Time\n        - Recurring\n        - Usage\n    PriceFrequencyEnum:\n      type: string\n      title: PriceFrequencyEnum\n      enum:\n        - ONETIME\n        - WEEKLY\n        - MONTHLY\n        - QUARTERLY\n        - ANNUALLY\n    PriceTypeEnum:\n      type: string\n      title: PriceTypeEnum\n      enum:\n        - Tiered\n        - Volume\n    FrequencyEnum:\n      type: string\n      title: FrequencyEnum\n      description: Billing frequency\n      enum:\n        - HOURLY\n        - DAILY\n        - WEEKLY\n        - BIWEEKLY\n        - SEMIMONTHLY\n        - QUADWEEKLY\n        - MONTHLY\n        - BIMONTHLY\n        - QUARTERLY\n        - SEMIANNUALLY\n        - ANNUALLY\n        - BIENNIALLY\n        - TRIENNIALLY\n        - ONETIME\n        - ENDOFPERIOD\n        - STARTOFPERIOD\n        - CUSTOM\n    AgreementTypeEnum:\n      type: string\n      title: AgreementTypeEnum\n      description: Agreement type\n      enum:\n        - Quote\n        - End User Agreement\n        - Reseller Agreement\n        - Other\n    AgreementStatusEnum:\n      type: string\n      title: AgreementStatusEnum\n      description: Agreement status\n      enum:\n        - Draft\n        - Out For Signature\n        - Signed\n        - Expired\n        - Cancelled\n        - Not Yet Sent For Signature\n        - EchoSign Account Payments Not Up to Date\n        - Other\n        - Out For Approval\n        - Approved\n    AgreementStatusResponseEnum:\n      type: string\n      title: AgreementStatusResponseEnum\n      description: Agreement status response\n      enum:\n        - draft\n        - out-for-signature\n        - signed\n        - no-agreement\n        - no-quote\n    ContractualDocumentTypeEnum:\n      type: string\n      title: ContractualDocumentTypeEnum\n      description: Contractual document type\n      enum:\n        - purchase-order\n    CreateSubscriptionConfiguration:\n      allOf:\n        - $ref: '#/components/schemas/BaseSubscriptionConfiguration'\n        - type: object\n          properties:\n            resellerId:\n              type: string\n            distributorId:\n              type: string\n            contractualDocumentId:\n              type: integer\n              nullable: true\n              description: |-\n                Id of contractual document object.\n      description: Model for subscription create\n    UpdateSubscriptionConfiguration:\n      title: UpdateSubscriptionConfiguration\n      allOf:\n        - $ref: '#/components/schemas/BaseSubscriptionConfiguration'\n    PaymentLink:\n      title: PaymentLink\n      type: object\n      properties:\n        type:\n          type: string\n        url:\n          type: string\n          format: uri\n      required:\n        - type\n        - url\n    Preview:\n      title: Preview\n      type: object\n      properties:\n        frequency:\n          type: string\n        totalAmount:\n          type: number\n        totalListPrice:\n          type: number\n        successPlanPremium:\n          type: number\n        items:\n          type: array\n          items:\n            type: object\n            properties:\n              code:\n                type: string\n              title:\n                type: string\n              quantity:\n                type: number\n              amount:\n                type: number\n      example:\n        frequency: Monthly\n        totalAmount: 110\n        totalListPrice: 220\n        successPlanPremium: 20\n        items:\n          - code: Kay-SA-TNK-STA\n            title: Kayako TNK Standard\n            quantity: 2\n            amount: 90\n          - code: Kay-SA-COL-STA\n            title: Kayako COLLABORATOR TNK Standard\n            quantity: 2\n            amount: 20\n    ExtendedPreview:\n      allOf:\n        - $ref: '#/components/schemas/Preview'\n        - type: object\n          properties:\n            priceIsValid:\n              type: object\n              properties:\n                isValid:\n                  type: boolean\n                  description: Indicates if the price is valid.\n                errorMessage:\n                  type: string\n                  description: Provides an error message if the price is not valid.\n                details:\n                  type: string\n                  description: Additional details about the pricing validation.\n              required:\n                - isValid\n            onlyPlatinum:\n              type: boolean\n              description: Indicates if only platinum plans are applicable. Returned only when previewing a platinum plan.\n      example:\n        frequency: Monthly\n        totalAmount: 110\n        totalListPrice: 220\n        successPlanPremium: 20\n        items:\n          - code: Kay-SA-TNK-STA\n            title: Kayako TNK Standard\n            quantity: 2\n            amount: 90\n          - code: Kay-SA-COL-STA\n            title: Kayako COLLABORATOR TNK Standard\n            quantity: 2\n            amount: 20\n        priceIsValid:\n          isValid: false\n          errorMessage: 'The price is not valid'\n          details: 'Renewal ARR: 100.00, Current ARR: 100.00'\n        onlyPlatinum: false\n  securitySchemes:\n    Token:\n      name: Authorization\n      type: apiKey\n      in: header\n      description: |-\n        JWT tokent signed and encrypted. Can store productFamilyCode, productVariantCode and customerID so results of all requests will be filtered by these values. See JWTToken model\n        ### JWT payload\n          * pfc: string // Product Family Code\n          * pvc: string // Product Variant Code\n          * cid: string // Customer id\n          * email: string  // Self Serve User Email\n    PrivilegedToken:\n      name: Authorization\n      type: apiKey\n      in: header\n      description: PrivilegedToken - same as normal token with padm=true in payload\n  responses:\n    Error:\n      description: General error\n      content:\n        application/json:\n          schema:\n            type: object\n            properties:\n              errors:\n                type: array\n                minItems: 1\n                items:\n                  type: object\n                  properties:\n                    path:\n                      type: string\n                    message:\n                      type: string\n                    errorCode:\n                      type: string\n                  required:\n                    - message\n    PartialResponse:\n      description: Partially successful response. Check errors for failed messages\n      content:\n        application/json:\n          schema:\n            type: object\n            properties:\n              errors:\n                type: array\n                items:\n                  type: object\n                  properties:\n                    path:\n                      type: string\n                    message:\n                      type: string\n                    errorCode:\n                      type: string\n                  required:\n                    - message\n  parameters: {}\n  x-examples: {}\nsecurity:\n  - Token: []"},{"id":"5258a340-c9f7-4cba-894f-06ca04c9b830","name":"Convert Video to Markdown (with transcript)","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"url\": \"https://drive.google.com/file/d/1xK_ZUaKw5F5ZK2_I7gjG4bIuNf9iC7Q3/view?usp=drive_link\"\n}","options":{"raw":{"language":"json"}}},"url":"https://pr131.productmind.trilogy.com/convert/url"},"status":"OK","code":200,"_postman_previewlanguage":"plain","header":[{"key":"Date","value":"Fri, 22 Nov 2024 17:47:21 GMT"},{"key":"Content-Type","value":"text/markdown; charset=utf-8"},{"key":"Content-Length","value":"21471"},{"key":"Connection","value":"keep-alive"},{"key":"x-amzn-RequestId","value":"e40301ac-5c93-4dea-b854-f31b727ded55"},{"key":"x-amz-apigw-id","value":"BqOCHF9WIAMECug="},{"key":"X-Amzn-Trace-Id","value":"Root=1-6740c3a6-0ced4d1c106ce70368564aa7;Sampled=1;Lineage=1:59f458cb:0"}],"cookie":[],"responseTime":null,"body":"MySight Module review – 2024/09/11 16:58 EET – Transcript\r\nAttendees\r\nAmmar Nofal, Caleb Andrada, Kirill Lanchev, read.ai meeting notes, Rob Austin, Rob Austin's Presentation\r\nTranscript\r\nAmmar Nofal: All good, take it away.\r\nRob Austin: But, okay, brilliant. So yeah, ahead of business intelligence for the last eight years at tivion. So me and my team create dashboards for our customers based on their survey results. So, I work in, Professional Services Department. So our\r\nRob Austin: Our implementation consultants, they help the customers create the surveys and we work with them to decide how that data is going to look on the output. We then work with the customers themselves to say, how they want their data, displayed, what the dashboard should look like. So we often start with the template and we'd say This will be kind of a standard thing and they go. Yeah, I like that bit but I don't like this bit and we need more information about some of these questions and so then we start have a conversation about how the dashboard will then look. So we come with it from two ends, we've got hopefully the finished mock-up, and then we've got the data and then we kind of bring it all together to Create the data source, create the dashboard and make sure it all fits and then we do validation, and qa and that kind of thing.\r\nRob Austin: Dxi creates a default set of tables. And this is basically all based off of the Mysight module. And so we can pick any survey or up to five surveys. We can pick which questions we want to pull out from those surveys. We can decide if we want to use them as filters or just as viewing results. And then we hit the Go button in the mysight module. It's spits out a bunch of tables into exile, which is our analytical database. It also creates. A. Tableau Server Data Source. And it joins all of the tables that it's created into the\r\nRob Austin: prescribed format, basically, with the joins set up as per a template then we get that as a tableau server data source and the reason we do it like this is so that the customers Are then able to create their own dashboards using tableau, if they don't want to use professional services but they don't get access so easily to the raw data. So, it's still within our protected environment and they can only access it through Tableau Server.\r\nAmmar Nofal: No, are you able to show us a quick demo on how all of that works together?\r\nRob Austin: Yeah, absolutely. Let's do that. So Let me.\r\nRob Austin: Bring up.\r\nRob Austin: Share my screen.\r\nRob Austin: Okay, so this is a dxi installation which we just use as our playground. So if I log into this one, it's actually on the sandbox area. So we don't have additional ETL tools, we don't have all tricks available to us in this environment, but we have everything else. so, I would Go into.\r\nRob Austin: maybe we'll start with the project. so,\r\nRob Austin: Here's a demo employee survey. And if we take a quick look at the question set, we can got some welcome things. Go ahead if we do a preview of this, We can see what this survey looks like. Employee survey. I would recommend on. So somebody has already filled out this to each of these questions.\r\nRob Austin: We're then going to use this Mysight module to pull out the relevant, questions to us and put them into a useful format. So, I'm going to pick my side project. Let's call this.\r\nRob Austin: A site. Which as you can see, we've done many times before.\r\nRob Austin: That's fine. and then, in here, I'm going to\r\nRob Austin: Pick an EFS project. So it's called Demo employee survey. So that's the one we were looking at. I can add another one, If I wanted to look at demo employee survey too, and then we could do year on year calculations comparing one survey to another and that kind of thing. So in here, I then pick, whichever questions I want. To hit our hands. Fat. Maybe we'll do everything.\r\n00:05:00\r\nRob Austin: Just looking at the types of questions, we've got it. Yeah.\r\nRob Austin: okay, and these are basically\r\nRob Austin: Sets of questions from the survey. And if I want to, I can turn one of these into a\r\nRob Austin: I could turn one of these into a dimension. So this would then allow me to use it as a filter and that just changes the shape of the data model slightly in the background.\r\nRob Austin: So this is the question said itself. We can then also add some metadata about the survey. So something I often put in is date of last access. That is basically the date when the respondent completed their survey. And again we might want to filter by this. So we can set as a dimension. participant data or don't think we have much in here but potentially we capture Metadata about the participant. And this is usually provided to us by whoever is setting up the survey. So if we're running an employee survey for British Airways, then they would give us information about their participants, and we would put that in the survey metadata Organizational structure. This is to do with the hierarchies.\r\nRob Austin: So again, a big organization will have a hierarchy starting at CEO and going all the way down to their lowest level of workers. And so we might bring in the organizational structure into here.\r\nRob Austin: Field report is really to do with the response rates. What? Percentage of people have completed this. We don't use this very often. It's very limited in its capabilities, and we have other more bespoke ways of getting that information. And then we have something called action planner. This is an add-on survey, which Customers can use to generate actions. For example, If I look at my data set and I can see that it's\r\nRob Austin: There's a problem and an area and I want to take some action, I can click through onto that I can generate an actions, puts it in a ban board and then we can monitor those actions a little bit like JIRA. but again, we can do dashboards based off of that if you were to create a custom dashboard off of JIRA, except we can put it into anywhere we like\r\nRob Austin: So this is the mysight module survey side. This access control is to do with the audience of the dashboard. So this is probably a different set of people to the people who are participating in the survey. Sometimes it's the same but often it's different. So that is administrated in this people module here. And we can set up the groups, so if there's any copy of my site, user has 24 people in it. And we can actually get some metadata about these people as well as we've got their name probably email address. We can add this kind of information in which might help us with any more complex roll-up security that we need to do or anything like that.\r\nRob Austin: We've also got these configurable fields master data, which is further information about our audience. So it might be like if we want to add something where they sit in an organization or maybe where they live, so that the rest, we can restrict the data down to those additional metrics as well. so, once we're done with setting it up, We click the Go button.\r\nRob Austin: I got a message just now saying that Tableau server was not available and that may be the case because it's a sandbox environment. that I'm showing you we don't use it very often. But that is possible, but hopefully this will work and we'll set us up a tableau server data source.\r\n00:10:00\r\nRob Austin: While we're waiting, I'm going to start up Tableau server on my local machine. what when we do real customer projects, it's not in the sandbox environment and we don't tend to work Off of our local machines, we've got workspaces set up in AWS so that we can actually get the data in the database if we need to. So, it's a very contained environment clients can't get into that, it's only. Within tivion or trilogy that anyone would ever have access. To that one.\r\nRob Austin: I'm just going to check the logs here to see if anything's actually happening in the background.\r\nRob Austin: Yeah, now we're moving. That's good. so,\r\nAmmar Nofal: And actually for new created installations, are there any specific configuration that you need to do other than My Site settings?\r\nRob Austin: So, because a brand new customers for brand new installations? Yeah, it tends to support that sets that up for us. I've never set up a brand new installation. I only have worked on existing ones.\r\nRob Austin: \r\nAmmar Nofal: And are you familiar with the backend code for this or repositories?\r\nRob Austin: \r\nRob Austin: So I've never seen it in theory. I know, kind of where it sits and that's sort of thing. So, My understanding is that. The databases are Maria, dB in the background and there isn't something they call an intermediate database. Which is used kind of for staging for my side. So I think this process Puts it into an intermediate database and then pushes that into Exosol. That's as I understand it but I never seen any of that code. I'm afraid.\r\nAmmar Nofal: but,\r\nRob Austin: Okay, it seems to be doing something. And I've been there.\r\nRob Austin: Failed to. So this works. Maybe a month ago.\r\nRob Austin: That when did we last set this up? It's saying it hasn't got a connection to Tableau server. So I'd only ever look so a month ago, I created this one that worked fine. Some of these broken, I would probably raise a ticket and say, Hey, my environment is broken and then hopefully somebody would either work with me to fix it or they would be able to take care of it. But that's not an area that I have any knowledge of I'm afraid.\r\nRob Austin: This is a installation which we use for demo is but this actually sits in our live environment. So we might have a little bit more success in this.\r\nRob Austin: yeah. Okay. So\r\nRob Austin: So yeah, we can see I won't create a new one again because I've shown you the process for that, but We've got. This test sandbox connection RV. Not sure what it is, but let's have a little bit of a look.\r\nRob Austin: so, I'm just gonna bring Tab, over here. Can you see that one? Okay.\r\nRob Austin: Do you see tableau or do you still see a\r\nAmmar Nofal: We're still on my side tank.\r\nRob Austin: okay. You don't see Tableau right? Let me, yeah. Okay. Let me\r\nRob Austin: Stop that one.\r\nRob Austin: And in fact, what, I'll jump into my workspace. As I only have it open.\r\nRob Austin: Yeah, once again.\r\nRob Austin: where is it? That you guys work, which section?\r\nAmmar Nofal: Mastery come again.\r\nRob Austin: Where do you guys work? Which department? Okay. …\r\nAmmar Nofal: Engineering actually.\r\nRob Austin: you're trying to take over My site code base. Okay, make sense.\r\nAmmar Nofal: Yeah.\r\n00:15:00\r\nRob Austin: All So I don't know if you've ever seen it before, but this is Tableau So, if I Sign into.\r\nRob Austin: Different site here. So that was the installation name.\r\nRob Austin: And if I, Connect to some data.\r\nRob Austin: We should be able to see. That one, which was called. Rv. I think it was called that.\r\nRob Austin: There we go. So, test sandbox connection of the\r\nRob Austin: So, that should in here.\r\nRob Austin: no. Sorry that's the one connection. Let's try S Company dashboards.\r\nRob Austin: It's not that. All right, let's just I'll pick one random.\r\nRob Austin: Let's testing.\r\nRob Austin: It does not respond, but that's okay. We can edit the one which does work.\r\nRob Austin: Okay, let's try that one. No, it doesn't matter either.\r\nRob Austin: One. Yeah. Okay.\r\nRob Austin: Not sure what we all have modified dates, the same as well. Some of this stuff you really old and might just not work anymore. Let's try this one.\r\nRob Austin: No, nothing.\r\nRob Austin: Okay, instead then show you a project which I'm currently working on. so, this is\r\nRob Austin: A data source. It's not the standard one. It's one that we've crafted a little bit but Should have the same sort of idea in here. So we've got a bunch of questions.\r\nRob Austin: Yeah, they're getting question hierarchy.\r\nRob Austin: Yeah, so we have some questions in here.\r\nRob Austin: And we've got some responses. And so here's basically a question set.\r\nRob Austin: And then we can start to interrogate. each of these, it's just\r\nRob Austin: learn to color. And let's just pick a couple of these questions that are a bit simpler. As you can see, survey data can be pretty. Diverse in how it looks, of it's never the same. There's no standardization to it. Somebody can create any question they want with any scale they want. So then putting that into a standard dashboard can be challenging. But we do have templates that we use and can make it a certain way. So now if we go to a simple,\r\nRob Austin: Like that. Then we can see that. We've got.\r\nRob Austin: number of toes three's fours. There's not a great data set unfortunately, but we can see how this breaks down and typically I think five is likely to be I strongly agree or something like that. And so we have a large portion of those and then we can do things like add the label in there. We can say, Okay, what's this look like as a percentage?\r\nRob Austin: And so then we can see, What 17% of my user base to this question? Answered with a five and maybe actually we want a group force and fires together. So we can go ahead and do that. So once you get your head around the data, you can very quickly manipulate the data into, the way, you want to see it, maybe we want to group the ones and the two as well. Something that customers often ask to turn that Into a three-point scale. So then we have good medium bad basically. And see that's not adding up to 100%. Let's just make sure how that's working computing table across.\r\n00:20:00\r\nRob Austin: That's a bit better. So yeah, this is the type of thing. that me and my team do we create these dashboards for the end user but yes, I do have a lot of experience using my site, but I don't have any backend experience and I'm afraid\r\nAmmar Nofal: Yep, that's good. I believe you provided us with everything regarding the front end or are there any other information that you'd like to add?\r\nRob Austin: So, we Probably something that's worth pointing out. Is that this is exersol?\r\nRob Austin: So here, I've got each of those schemas. So this was the one that I tried to use cm0955 which Through errors for whatever reason. But it looks like we do have tables in there and These are fairly Tables. I don't know where this number comes from this. Long number it's very inconvenient because it pushes everything off to the right? But basically this number 836 will be the same for every table. Within this s for a bigger difference schema then that will have its own one fa3 identifier.\r\nRob Austin: But yeah so all of these always the same anything that's different is a custom table created probably by me or my team and we will then join that into the data model.\r\nRob Austin: The data model is reasonably standard out of EFS. It's always joined in a certain way. It always starts with the fact table tends to be a star schema with a bit of a snowflake to it. But in essence it's a Kimball methodology. type of data model that is created and I believe it does this from a template\r\nRob Austin: let me show you Tableau server.\r\nRob Austin: So, this is the production. Server.\r\nRob Austin: and again, let me go back to that other one I was on CM and 955.\r\nRob Austin: And in here, we've got projects and within each project we'll have a Mixture of data sources. And workbox. So, anything that is owned by technical support was created by EFS. And these data sources are basically Within a schema essentially. And again, it seems to like it's broken but maybe just something that we can fix. This is an old exosole server actually, so it's looking for something that no longer exists. Maybe you're probably aware. We did our AWS migration.\r\nRob Austin: Earlier this year and pretty much everything was migrated, but there may still be some content that is pointing at old servers or old databases and needs to be moved across. We moved everything that people would want, but some of the old unused content, it seemed like a waste of time to do. So We prioritize the customers, then the live demos, and then anything else that we thought would be useful and just the stale content, just got left. we're intending to take on a project to clean up the server and whether that means we fix some more of these or whether that means that we just Delete it without things that are not needed. Now, probably happening in Q4 this year. I imagine\r\n00:25:00\r\nRob Austin: So yes, table. Let me pick Something that I know does have content. That works.\r\nRob Austin: so, I finally\r\nRob Austin: Yeah, we can see there's a whole bunch of dashboards in here that have been created over the years. Or maybe different versions of the same dashboard and then we've got a bunch of these data sources as well. So if I look at one that was created by ten minutes support. This should be a standard one. And ask data is a preview of it. Looks like it's not going to work. For whatever reason seems to be a common theme for today.\r\nRob Austin: Let me do a new. Workbook using that data source. This is the online version of tableau, it doesn't have as many. Capabilities. As the dablo desktop that I was using just now, but you can do pretty much the same thing. So again, if I pick that question hierarchy, To question. Do you responds? I think we've got languages set up here. so,\r\nRob Austin: if I decide, I just want this in English that will get rid of a load of those What did I do before? I did.\r\nRob Austin: It's your value. that's,\r\nRob Austin: Again, and I'll just keep a couple of these. but exactly the same thing as before, say,\r\nRob Austin: This is a really similar environment to the other one. We can create a dashboards.\r\nRob Austin: Basically, you could create all your sheets and then you put them into a dashboard and then you interact between the two and you can float images over and then you start to make them look all nice and sexy and something that the customer wants to see.\r\nRob Austin: the only piece of the puzzle I haven't showed you was how we create these so we can either script them in SQL. Or we have a tool called Alterx that we can use, which is an ETL tool. So, here, for example, I'm just taking a fixed set of data and pushing it into exercise. Probably don't need to use an ETL tool for that but I did. So we can then set this up to run on a schedule or we can set it to run so that any of my team can pick it up and use it. But that's basically, one of the ways that we can get these bespoke tables into our schema. I'm not sure how much that affects you guys. I imagine all your work will be\r\nRob Austin: Up to this bit Really creating these tables from what we call Dxi.\r\nAmmar Nofal: And are there any performance buttons that you are aware of?\r\nRob Austin: do you mean dashboard performance or do you mean data source creation performance?\r\nAmmar Nofal: Yes.\r\nAmmar Nofal: More of data source. I'd say creation performance.\r\nRob Austin: I think we were doing one earlier. so Maybe this one here. Refresh so that I was working with the colleague earlier to live project and we reset it and probably you can see that. I reset that at 140 my time. And then we waited waited. And it wasn't until\r\nRob Austin: 10 minutes later that it actually started pulling data in. and there are Chron jobs that run in the background that basically trigger this kind of thing, and I feel like that could be optimized I don't see why we need to up to 10 minutes for it to know that something is needed, and to kick it off. so that would be one. performance, blocker, I would say\r\nRob Austin: Because we've upgraded exersol I suspect that we can improve the performance of this probably just with configuration quite a lot. I think it used to be we didn't want to overload the database with too much data coming in because it might hurt the performance of reading the data on the way out. But I don't think that's the case anymore. I think we can be quite aggressive with putting data into the database.\r\n00:30:00\r\nRob Austin: Yeah, as other sort of thing you meant that one. Okay. Yeah,…\r\nAmmar Nofal: Yes, exactly.\r\nRob Austin: And this would be great if we could get rid of this time delay, that would be amazing. and in terms of the performance of the dashboards themselves, they're actually pretty good these days since we upgraded to AWS the performance have got a lot better. But if the performance is bad, that's when me and my team start looking at the data models, and maybe we need to aggregate data for the customer or something like that. So we tend to take care of that for the customer side of things.\r\nAmmar Nofal: That's good. Thank you ob. I believe I don't have any questions from my end Carol or…\r\nRob Austin: No problem.\r\nAmmar Nofal: Caleb. Do you have any questions?\r\nKirill Lanchev: Not on my side.\r\nCaleb Andrada: Nothing. Yeah.\r\nAmmar Nofal: Okay, then, I think Rob we can wrap this up. Thank you very much for your time. And have a good rest of your day.\r\nRob Austin: Yeah, no problem. If you have any questions, Yeah, and yeah, if you got anything else,…\r\nKirill Lanchev: Thank you.\r\nRob Austin: just reach out.\r\nAmmar Nofal: Absolutely, cheers.\r\nRob Austin: Thanks everyone.\r\nAmmar Nofal: Take care. Bye.\r\nCaleb Andrada: Here's everyone. Thanks.\r\nMeeting ended after 00:31:35 👋\r\nThis editable transcript was computer generated and might contain errors. People can also change the text after it was created."},{"id":"a20e1021-c1b7-426c-9883-6dde41079587","name":"Convert Video to Markdown (no transcript)","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"url\": \"https://drive.google.com/file/d/1qvxYcYbbS0ywyzjrzcT-plVyzjJMLqDY/view?usp=drive_link\"\n}","options":{"raw":{"language":"json"}}},"url":"https://pr131.productmind.trilogy.com/convert/url"},"status":"OK","code":200,"_postman_previewlanguage":"plain","header":[{"key":"Date","value":"Fri, 22 Nov 2024 17:48:16 GMT"},{"key":"Content-Type","value":"text/markdown; charset=utf-8"},{"key":"Content-Length","value":"29629"},{"key":"Connection","value":"keep-alive"},{"key":"x-amzn-RequestId","value":"cac286d1-450e-42ba-a3d1-8b5f7147d2b0"},{"key":"x-amz-apigw-id","value":"BqOKNFx_IAMEonw="},{"key":"X-Amzn-Trace-Id","value":"Root=1-6740c3da-1a5211e4658b56a970c0a7e1;Sampled=1;Lineage=1:59f458cb:0"}],"cookie":[],"responseTime":null,"body":"00:01 - Speaker 0\nHello everyone. And welcome. I'm excited to spend some time chatting about contently with you all. Thank you so much for being here and taking time out of your day. Okay.\n\n00:15 - Speaker 0\nSo just by way of introduction. Hi, my name is Ashley Allen. I am the head of product here at Contently. Great to meet you all. And I appreciate you taking time out of your busy days.\n\n00:26 - Speaker 0\nI wanna tell you a little bit about what we're going to do today during the demo. 1st, I'm going to walk through a few of our slides to help better help you better understand Contently and what we offer. Then I'm going to take a high level demo tour through our product. Then I will come back and share some of our customer stories and the results that we drive. Okay.\n\n00:52 - Speaker 0\nSo let's talk about Contently. So Contently started over a decade ago, really before content marketing was even a job title. And the benefit of that is that Contently essentially has evolved and grown to meet the needs of enterprise content marketing teams. Our mission is to ensure our clients have successful content, both now and for many years to come. Our offering is an end to end solution, and that means you can do everything from strategy, execution, analysis, all can be achieved on our platform.\n\n01:30 - Speaker 0\nSo how do we deliver these results to our customers? So really, Contelly isn't just providing you a bundle of all the tools that you saw on the previous slide. Our foundation is based in the product in these three pillars, services, talent, and technology. 1st, we have our global creative marketplace, which consists of a 165,000 registered freelance talent from all over the globe. This is a highly vetted global community of award winning content creators to really help support the creation of any content imaginable.\n\n02:07 - Speaker 0\nSecond, we have our content creation services, supporting strategy and content creation operations. Whether you're looking for a managing editor to manage your operations, an art director to help with imagery, a dedicated content strategist, or an SEO specialist, we have those specialized experts in our network ready to support you and your staff as you need them. Finally, we empower you with our content marketing platform that makes all of it possible. The Contently platform is really mission control for your content operations. You can document and align your teams around your strategy, ideate and collaborate on content ideas, manage your content calendar and plan your your content plan, and optimize your content for better performance.\n\n02:53 - Speaker 0\nIt all comes together here, and I will be showcasing that to you in a few minutes. But let's dive into the depth and breadth of the global creative marketplace. If you need a subject matter expert, say you're looking for a freelance writer who's aware of complex hacks law, or you need someone with scientific research background, or a talent or a travel guru, we really have that here and everything in between. So don't hesitate to leverage our network of expertise to to exemplify what is important to your brand. Now what we hear most often from our clients is that they're really trying to scale their content programs.\n\n03:33 - Speaker 0\nThey may be producing 1 to 2 pieces of content per month, but really they wanna scale up to 5 or 6, for example. And really there's no limit to how much content you can produce with our freelance network. Really, it allows you to cover ground on as many topics that are important to you, your audience, and your marketing goals. But we don't just stop at written content. We know your audience is consuming content on your blog.\n\n04:01 - Speaker 0\nThey're consuming multimedia content in a variety of channels, and you need to meet that audience wherever they are. So whether you need a copywriter, editor, videographer, podcaster, photographer, graphic designer, we have an array of profiles at your disposal. And so if you can dream it, we can help you create it. And let's talk a little bit about the platform because this is really where the magic happens. Our platform is an AI driven comprehensive content solution.\n\n04:35 - Speaker 0\nThe platform was designed and has evolved to support common pain points, such as organizational silos, lack of strategic alignment, quality control needs, and lack of resources. All of this leads to content chaos. And that's what we're gonna help you eliminate and leave behind for 2024. So let's walk through the platform. I'm going to highlight how we can improve your strategic alignment by centralizing your strategy, how you can supercharge your content programs velocity with our workflows and collaboration, And finally, ensure that you are producing top notch quality with our optimization tools for SEO, brand compliance, and organizational compliance, as well as managing your content performance with our robust analytics suite.\n\n05:25 - Speaker 0\nOkay. Bear with me as I move over to our demo. Okay. Alright. So before I jump into the product, I wanted to show you the content strategist.\n\n05:50 - Speaker 0\nThis is our foremost content marketing blog that helps every helps deliver everything from thought leadership to how to articles within content marketing. And I welcome you to review this at any time, but really the reason why I'm showing this to you is because this helps you helps demonstrate what the platform could do for you. Everything that you see in this blog was created in the Contently product. So without further ado, let's jump in. Now I'm gonna take you on a journey through the product from beginning to end.\n\n06:22 - Speaker 0\nWe'll talk about the content strategy. We'll go through talent sourcing, ideation, planning, creation, management, distribution, and analytics. So let's start with the content strategy. As content marketers, we know the content strategy is the pillar of everything that we write. So within Contently, we we encourage you to centralize it on our product because once you've centralized the content strategy incontently, it can help power both the people in the platform and the the tools that we have in the platform to ensure that everyone is on the same page around what goals you're trying to achieve and producing content that meets those goals.\n\n07:04 - Speaker 0\nSo first within goals, this is a fully customizable form that essentially allows you to determine what your primary goal is, your organization type, define your content mission, provide your KPIs, and even upload something like a brand guide for instance. In addition to the goals, we also have, areas where you can input your audiences. So you can create those audiences and, again, fully customize those. You can have as many as you need as well as pillars. And pillars are thematic elements of your value proposition that you may be that you may need to speak to to your audience.\n\n07:42 - Speaker 0\nNow what's great about these is that they come through in all almost all aspects of the product from talent sourcing to creation as well as analytics. So once you populate your pillars, your audience, and your goals, you can start to plan your content, around these goals and ensure that you're really meet meeting all of those, pillars that you've outlined as well as the audience that you've defined. We also allow you to upload your SEO keywords into the product. Again, this is a great way to centralize those keywords in one place, but also empower those tools and people in the product that are creating content on your behalf. Here you have a list of keywords, number of results, search volume, as well as cost per click, information to help you optimize your SEO strategy.\n\n08:34 - Speaker 0\nK. That's a high level view of the content strategy tools we have. I'm gonna jump over and show you how you can start to source talent within the Contently network. So the first tool, that we I wanna share with you is our intelligent talent recommendations. And as I mentioned, the content strategy that you enter will really build a lot of relevance and quality throughout the experience.\n\n08:57 - Speaker 0\nAnd the first way that we do that is with intelligent talent recommendations. This list of freelancers is really derived from your content strategy and pieces of content that you've produced in the product. And when you've got these recommendations, you can take a sneak peek at these writers. You can understand their headline, their bio, can view relevant stories. You can even view their portfolio on the content.\n\n09:16 - Speaker 0\nRelevant stories. You can even view their portfolio on the Contently platform. And if this person is something that you're interest is that this person is something you're interested in, you can click on this button and you can invite them to pitch, essentially start exchanging ideas with them on the platform, or you can just invite them to your team. And when you invite them to your team, you can start staffing them on content. However, if the intelligent talent recommendations aren't delivering the talent you're looking for, you can always do a, a talent search.\n\n09:46 - Speaker 0\nSo you create talent search and you define all of the parameters you have for that talent resource. And once you've done that, that those resources will again show up on this page. And just as before, you can, you know, add them to your team, invite them to pitch. However, if none of this really meets your goals, you can create a custom talent request, which essentially reaches out to Contently Resources to help you find the bespoke talent resource that you're looking for. Now once you've staffed your team, you can start to generate ideas with that team.\n\n10:21 - Speaker 0\nAnd there's a 3 different ways that we do that within the Contently platform. 1 is with pitches, the other is SEO story ideas, and last but not least, content requests. So I'm gonna walk through all three of these. So within pitches, there's really two ways that you can initiate pitches. If if you have an idea yourself, you can create a pitch and submit your idea to your content marketing team.\n\n10:44 - Speaker 0\nHowever, if you're looking to produce content on a very specific topic, you can create a pitch request. And that will go out to your internal writers or the freelancers that you've sourced from the Contently team and start to generate ideas from, that team of writers or freelance creatives, whatever content you're looking to produce. Now when you have a pitch in here, it's it's great to have it in the product because it's completely streamlined. You can have commenting and messages back and forth to mature that idea. You can even if you accept this idea, you push it into a story, and it's ready to go for creation.\n\n11:18 - Speaker 0\nIt pipes right into your production operations. Next, we have SEO story ideas, and this is really a great way of identifying the white space in your SEO keyword strategy. What this is is an algorithmic recommendation of story ideas based on the keywords that you've updated and what people are searching for. So what are what topics or content are people looking for online that are relevant to your SEO keywords that you may not be hitting with those exact keywords? So it really helps you reach those, customers where they are and deliver topics that they're looking for.\n\n11:57 - Speaker 0\nNow what we see with our SEO story ideas is a 76% acceptance rate of these ideas. So we know that these ideas are really hitting the mark for our content marketers. Next, we have content requests. As content marketers, you know ideas come from everywhere and you have many stakeholders who are requesting content for their individual needs. So centralizing all those requests in one place is the key benefit here of the content requests forms.\n\n12:26 - Speaker 0\nSo you can create these forms for different teams and you distribute that to to everyone within your organization so they can submit your their ideas and essentialize here. So as the content marketer, you can turn that chaos of ideas coming through Slack, through email, through Teams, and have all those ideas right here so you can prioritize the different ideas, identifying any duplication of requests, any requests for content that you've already produced, all of that can be managed here. You can also accept or decline these ideas in one centralized location. Right. So that is ideation.\n\n13:05 - Speaker 0\nI'm going to jump over to planning. And, of course, no planning tool is complete without a calendar. And the Contently calendar is really our users' most one of our users' most favorite features. And the reason for that is it goes above and beyond a typical calendar that you may have. 1, these cards are custom built to display the information that is most relevant to you, the content marketer.\n\n13:29 - Speaker 0\nSo we tell you if there's anything overdue, what type of content you're producing, what is the headline, who's on point for this step, what step they're in, and how much progress you've made against that workflow. So it's a really quick way to identify the status of your program at a at a bird's eye view and make adjustments as needed. And if you need to move any dates, you can easily drag and drop those stories to different dates. But one really powerful feature of this is as we work in enterprise organizations that are fairly matrix, there's a lot of different teams that may be producing content. And you may need to coordinate across those teams to ensure that you're not duplicating efforts or potentially dropping the ball somewhere.\n\n14:12 - Speaker 0\nSo within Contently, you have the idea of instances so you can quickly at a glance see what different people are producing in their instance. So as you see, I'm adding some publications here, and new cards are appearing that are color coded for that specific publication. So all of that is managed within the content calendar, and it's a a really great way to keep track of of your meeting your goals of content production as well as collaborating with your teams within your organization. Okay. So let's go ahead and jump into content production.\n\n14:49 - Speaker 0\nSo within Contently, we have a lot of really great features to support the creation of content. So one thing there's there's one major differentiator that our tools have when compared to say Google Docs or Word Docs. When you're working with Google Docs or Word Docs, generally speaking, you're looking at, collaboration, version history, as well as commenting. These some of the these are some of the core features that you need within those products to really solicitate sorry, solicit feedback from, your internal teams. So I'm gonna show you how we meet those needs within the Contently platform.\n\n15:27 - Speaker 0\nSo commenting is super easy. You can highlight any piece of, copy here, and you can annotate your comment. You can, at mention or tag any user within your organization, And you can have a dialogue back and forth with those comments. You can maintain a history of all those comments. Look at both the open comments and the resolved comments for future reference.\n\n15:52 - Speaker 0\nAlso, we have a very robust version history tool. So right now, we're looking at the current version. But if I wanted to go back a little bit, I can see which version number that is. I have a time stamp of when it was, created, and I also have an owner of that version. And when I compare those versions, I scroll down, I can see the content that was added, the content that was removed, and keep track of all of those changes.\n\n16:16 - Speaker 0\nSo I know this is something that you you may use a different text editor for, but where it contently goes above and beyond is, with our requirements tab. Now the requirements tab is a great way to maintain awareness of the objectives of that story. What are what are you trying to convey? Who is the audience? And what is the goal of this piece of content?\n\n16:40 - Speaker 0\nAdditionally, all that information that you've uploaded into the content strategy is right here, just a click away, and your writer's producing content can easily reference that. And what we've heard from our customers is having all this information at the ready essentially reduces the number of versions that you're creating from say, you know, 10 versions down to 2 versions. So maintaining that strategic alignment in the forefront really drives a lot of meaningful results for your organization. We also have this review tab that helps ensure that you're meeting your quality and guidance within your organization. So within quality, you can see examples of where we have, misused words, any example of passive voice, for instance.\n\n17:26 - Speaker 0\nAnd then in the optimization tab, we can make recommendations for the story. So for instance, what is your reading time, your character count, and the SEO keyword selection that you've added? It will tell you if it appears in the headline, how often it's in the body, or in the subheader. So you can start make making optimizations to this content. It will also tell you if we're missing all texts as well.\n\n17:47 - Speaker 0\nSo all of these tools ensure that you're re meeting your brand compliance. I also wanna talk a little bit about how you how you can manage the workflow of the content creation. So our workflow is really purpose built for creation of content. It works alongside with any project management tool that you have within your organization. But the the intent of the workflow is really to manage the handoff between one collaborator to another.\n\n18:17 - Speaker 0\nSo within here, you can see there's an owner of that, workflow step. There's a description of what needs to be done as well as due dates. And we also have a payment, option in here. So if you are paying our freelancers, you really don't have to worry about additional paperwork. Once that story is completed, you can pay that freelancer straight away.\n\n18:39 - Speaker 0\nAdditionally, as you're working with multiple people in your organization, this workflow essentially makes sure that everyone has editing access when it is appropriate for them. So you may need your your subject matter expert to be one of the first people to weigh in, but your legal team to be one of the last people to weigh in. So all of that is managed through the workflow. However, if you do wanna work concurrently, we do have a a new collaboration feature. So I'm going to move to a different window and start typing in a different window, and you can see that information is here in real time to boost that real time collaboration with different writers as well.\n\n19:16 - Speaker 0\nSo you can designate the real time collaboration or manage the work manage the editing through the workflow itself. Last but not least, a lot of our customers are from highly regulated industries, and it's really important for them to keep track of the changes of the document for any auditing purposes. So in addition to the version history and maintaining all the comments as well as the workflow to track approvals, you have your activity log here that highlights every step of the process, who's made comments, who's manually transitioned steps, who's submitted stories. All of that is a time stamp with the user, the action, and the time. And that is something you can download and share with anyone in your organization anytime you need to audit your content.\n\n20:03 - Speaker 0\nOkay. So that is creation. I am going to talk a little bit about how you start to manage this content because what we've heard from our prospects is you can produce, you know, a few pieces of content a month, but when you start to produce a high volume of content, it becomes very difficult to manage the different teams and the different content running through your your team. So within Contently, we've thought a lot about this, and our tasks redesign really helps serve 2 different users' needs. The first user is anyone on your team who's really sort of an individual contributor to the content.\n\n20:34 - Speaker 0\nMaybe they have one job within a story, or 2 jobs, but really, they just need to come in, get the work done, and leave. So when they come into Contently, they're going to see this task page. And if they click on on this, they'll be taken directly to that page where they can start their job and get, and finish that as quickly as possible. So this acts kind of like a to do list for them. However, we know a lot of content marketers act as air traffic control.\n\n21:01 - Speaker 0\nYou're managing the different stories you have in the in the platform. You're ensuring you're meeting your deadlines, and there's a high volume. So it's really important that you keep track of everything. So publication task gives you a high level view of what needs your attention. What is overdue?\n\n21:15 - Speaker 0\nWhat have you put on hold? Are are any steps unassigned? And what is ready to publish? And that's just at a glance. Last but not least, you can come to the activity tab and see a play by play of all the activities happening, with your content in the platform.\n\n21:35 - Speaker 0\nAnother really powerful tool we have for a management of high volume of content is our campaigns. Once we see our customers producing a certain volume of content, campaigns becomes one of their favorite features. And this is because it allows you to create a campaign where you can set a specific goal or objective against that campaign as well as a a a timeline against that. So within Contently, we are working on a few things like, our social media, for instance, or our content refreshes. And so we have a a goal of 19 stories, and we can see the progress of those of those stories.\n\n22:09 - Speaker 0\nWe've completed 10 and 8 are in progress or overdue. And we also here have, built in analytics around the performance of that specific campaign. So it's a really great way to to create a subset of content that you need to track the progress and performance against. Alright. Now I'm gonna jump into integration.\n\n22:30 - Speaker 0\nSo at Contently, we know that you have a variety of tools that you're working with within your organization. And I'm sure the first thing you're thinking is your CMS. How do you get content out of Contently and into your CMS? So we have out of the box integrations with Adobe Experience Manager, Drupal, WordPress, and we also have a custom integration which supports most other CMS tools that you may have. We also integrate with the major social channels, as well as a Salesforce integration that allows you to surface the content that you have in Salesforce so your team can use that to nurture their leads.\n\n23:07 - Speaker 0\nWe also have a custom API for anything else that you need to do. And we are investing heavily in expanding, our integrations for 2024. The next focus we have is project management tools, and then we will also round out our CMS tools and provide many other integrations. Okay. Let's shift over to analytics.\n\n23:31 - Speaker 0\nSo we understand that most organizations are using Adobe Analytics or Google Analytics as our source of truth, and we're not trying to replace those tools. We're really trying to provide supplemental information that is critical for content marketing teams that maybe wouldn't be surfaced through a sort of a web analytics tool like Google Analytics. Now the first area is around production. How are your content operations doing around the the volume of content that you're producing? And we have, dashboards like stories completed by day, average price per story, who are your who are your, most productive contributors, how is performance against those contributors, all of that is within the view.\n\n24:18 - Speaker 0\nWe also have custom built dashboards specifically for performance metrics, like brand awareness and lead generation. So these dashboards are built for you to to take a look at those specific metrics to help inform how your content is doing against those goals. And these dashboards are customizable. You can drag and drop them. You can add new cards.\n\n24:40 - Speaker 0\nYou can remove the cards, all really to support your needs and getting information as quickly as possible. We also have a tool called Docalytics, which essentially provides a heat map of any hosted document that you you that you publish through Contently. So what this provides is an engagement score by page, tells you how the readers are dropping off in your content, and really what content are they focusing on. So you can produce better content going forward. Last but not least, we have the content value tracker.\n\n25:16 - Speaker 0\nNow the content value tracker is a great way for you to demonstrate to your leadership team the value of content marketing. Unlike paid media, which essentially is a flash in the pan, if you spend your money, you see the results within a few weeks. Really, content marketing pays dividends over time. So once you produce a story month after month, it's going to deliver results to you in terms of traffic. And what is the value of that traffic to you?\n\n25:39 - Speaker 0\nWell, what this chart is telling you is how much you would have had to pay in search engine marketing to drive those same results in terms of of, traffic to your site. So as you can see, Contently is moving from, up up into the right because of the more content we produce, the more value we deliver to our organization. Alright. Now that concludes the platform demo. Okay.\n\n26:11 - Speaker 0\nSo let's talk a little bit about case studies. I don't wanna tell you we're great. I want our customers to tell you that we're great. So the first one we'll talk about is Coast Capital. They are one of our powerhouse users.\n\n26:22 - Speaker 0\nThey came to Contently looking for an all in one solution to hone their content strategy and production while heavily focusing on organic SEO. They needed to keep their customers up to date during crucial times and updating their content program was the main vehicle for that relationship with our customers. As you can see, Coast Capital increased our production from an average of 20 assets to over 400 assets and counting. So they're really able to meet the demands of their content organization. Not only that, but they also increased their average time on page from 7 to 15 minutes.\n\n27:02 - Speaker 0\nAnd they knew that their customers were also engaging with multimedia content. And this ultimately resulted in the 1st page ranking on search engine results page, which really, again, underscored the performance of this program. The full case study can be found on our website if you would like to learn more about this. And we also wanted to look to g 2. G 2 were really proud to be a leader in g 2.\n\n27:29 - Speaker 0\nUnlike most pay to play awards, g 2 really puts our customer reviews front and center, and we are so proud of our clients. We're honored that they are consistently show their appreciation through g 2. And those are customers like Dell, American Express, Marriott, and Synchrony to name a few. Alright. So that concludes the presentation portion, and I would like to stay on for some any questions that you might have.\n\n27:57 - Speaker 0\nBut I also would like you to subscribe to the content strategist. Follow us on LinkedIn. And if you have any questions, reach out to us at marketing at contentlink.com or drop us a line. Okay. So if you have any questions, please add them to the chat now.\n\n28:22 - Speaker 0\nOkay. It looks like we have a question here. How does Contently support AI features or AI content production? That is a great question. So at Contently, we firmly believe in the power of AI.\n\n28:36 - Speaker 0\nWe know that AI is really going to, accelerate the pace of content production and really help content marketers become more efficient. And we have a lot of features on the road map in 2024 that will help accelerate the pace of that content production. However, we strongly believe that a great content marketing program needs authentic voices and and expert opinions. So that is still something that is coming from people. So how do we make those people more effective at that work?\n\n29:08 - Speaker 0\nAnd what we're working on is, providing ways to take your original content, make it more digestible, and distributable across different channels. We are looking at ways to optimize your tone analysis as well as tools to help you detect if AI is being used in your content. So all of that is coming to life in 2024 on Contelly. Okay. It looks like we have one more question, and please drop in any more questions now if you have any.\n\n29:42 - Speaker 0\nBut it looks like, we're the question is, my legal team needs to review every piece of content and won't log in to additional tools. Yes. This is not a unique problem. We've heard this from many of our customers. So we do have a tool called the off platform review.\n\n29:59 - Speaker 0\nAnd essentially within the workflow, once you meet that step, we will trigger an email to your your legal team so they can open that up and review the content there. So it's a great way to help them, achieve the goal they have of reviewing the content and keeping everything centralized within the Contently platform. Alright. I think that is all the questions we have. I wanna thank you all again for your time today.\n\n30:27 - Speaker 0\nI know your time is valuable, and I'm glad you chose to spend it with us. Hopefully, we'll hear from you soon. Thank you.\n"},{"id":"ac6652c9-0b80-4b04-a8d9-d63df9d818a9","name":"Convert Notion to Markdown","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"url\": \"https://www.notion.so/trilogy-enterprises/ProductMind-P2-Spec-41002cfbc82545ef9bf08da95ba89ad6\"\n}","options":{"raw":{"language":"json"}}},"url":"https://pr131.productmind.trilogy.com/convert/url"},"status":"OK","code":200,"_postman_previewlanguage":"plain","header":[{"key":"Date","value":"Fri, 22 Nov 2024 17:49:14 GMT"},{"key":"Content-Type","value":"text/markdown; charset=utf-8"},{"key":"Content-Length","value":"8741"},{"key":"Connection","value":"keep-alive"},{"key":"x-amzn-RequestId","value":"2d360974-a05c-4436-ba33-77935b8f49ae"},{"key":"x-amz-apigw-id","value":"BqOT7HbhoAMEjKg="},{"key":"X-Amzn-Trace-Id","value":"Root=1-6740c418-0ccaa3c547eb4a465e305d5c;Sampled=1;Lineage=1:59f458cb:0"}],"cookie":[],"responseTime":null,"body":"# ProductMind P2 Spec\n\n\n## Background\n\n- There is a lot of raw data, structured and unstructured, about a product or company that ESW acquires. This includes things like files, financials, product videos, log files, support tickets, etc.\n\t- This data serves several functions in the company, including engineering, technical product management, commercial product management, sales, support, finance, and executive management, e.g.\n\t\t- SME interviews, product demos\n\t\t- Sales/Marketing materials - presentations, PDFs\n\t\t- Code & architectural design information\n\t\t- Sales documents - contracts, invoices\n\t\t- A lot of data is secluded in 3rd party systems - helpdesk software, CRMs, ERPs, accounting etc\n\t- This content comes in all sorts of shapes and sizes: text (lots of input formats) but also richer media (images, graphs, charts, tables, videos)\n\n## Problem statement\n\n- We need a way to consistently get to the right information, both so humans can find the information and also to help the entire organization adopt AI by enabling people to build assistants that benefit from the enhanced RAG.\n\n## Solution \n\n\n### Approach\n\n- Structure the data in a hierarchy by its quality, with raw data from the target at the bottom of the pyramid, summaries/insights in the middle, and polished work units (e.g., Stickiness Evaluation) at the top, enabling open exploration of data by leveraging all the layers.\n\t- Level 1 is the raw data. Ingested data is used with an LLM so someone can ask questions about the data and get good answers. Putting it all into a RAG is a baseline approach, but it may not be the best.\n\t- Upper levels contain more value. These are condensed insights/summaries thoughtfully created from the raw data and injected back into the knowledge base, such as auto-generated context packs, stickiness reports, and key feature extracts.\n- The bottom layers should leverage 3rd party no-code solutions as much as possible to avoid duplicate effort and the \"steamroller effect\". The top layers represent more durable IP in things like second brains.\n- We want standard patterns and architecture to apply across different products/teams at ESW to gain leverage and scale, rather than each team building its own siloed solutions.\n- Second Brains represent the most valuable IP - the unique insights on what information is most important to extract and represent.\n\n### Data & Schema\n\n- L1: Raw content (documents, code, videos) is imported from the A&I data room or 3rd party apps into a product knowledge space and indexed\n\t- Content is tagged manually (function, type, status, date) to improve retrieval\n\t- Documents are pre-processed/enriched for use with AI when needed (ITD #3)\n- L2: Context Packs capture specific, typed product information (e.g. product features, data model, commercial model), that serves as a base in creating work units\n\t- Content is created through GenAI flows based on raw data and indexed/tagged for reuse (e.g. creating the feature pack from product videos using Gemini)\n\t- Context packs include Thoughts (include CQs, Doubts, Assumptions, and Unusual Facts). These are then used as a basis for AI-led customer interviews aimed at clarifying/confirming the thoughts\n- L3: Work Units are complex deliverables created based on L1 and L2 information\n\t- Content is created through GenAI-enabled tools (e.g. the spec writer in TPM or stickiness unit in CPM) and indexed/tagged for reuse\n\n[link_preview](https://lucid.app/lucidchart/53adf0ab-6bd9-45b8-a57d-810ae0c02c63/edit?beaconFlowId=AE07B432EF9307BA&invitationId=inv_ebe8222b-45de-410c-9d55-59521ce43a59&page=0_0#)\n\n\n## ITDs\n\n1. **Structure data into three layers: L1 raw data from the acquired company, L2 refined&highly reusable data, L3 work-units**\n\t- L2 product data/documents that are commonly reused across work units (e.g., feature lists and pain/features/benefits of a product used in CPM&TPM, etc). This concept does not exist today in ESW, but having these stand-alone, reusable data items avoids duplicate efforts and improves quality\n\t- L3 work unit documents - are different from L2 data in purpose; if L2 data is designed to capture a specific type of information (Stickiness Analysis, AI Roadmap, S2) and be reusable, L3 (WUs) are designed to answer an important business question or drive decisions.\n2. **Use AWS serverless solutions as the main stack for semantic search/retrieval.** Although this is a fast-evolving space, it will become commoditized much faster than database hosting did, and AWS is already keeping up with the latest developments (e.g., [hybrid search](https://aws.amazon.com/blogs/machine-learning/amazon-bedrock-knowledge-bases-now-supports-hybrid-search/), i.e., combining semantic + text search).\n\t- **Use AWS Bedrock** [**Knowledge Bases** ](https://aws.amazon.com/bedrock/knowledge-bases/)**as the main retrieval engine.**\n\t\t- Note: We would have preferred to use **Amazon Q Business** because it has a [<u>long list of connectors</u>](https://docs.aws.amazon.com/amazonq/latest/qbusiness-ug/connectors-list.html) (including Google Docs, Google Sheets, GitHub, Confluence, Zendesk, Jira, Salesforce, SQL, etc), but this was not chosen because Q Business cannot be used just for Retrieval (it only supports Retrieval + Generation), and it’s [Generation quality is poor](https://docs.google.com/spreadsheets/d/1kdlvaXVFM6-Q6O-wufAtvTNKfq8pJIHpGfoXZpGzYC0/edit?gid=0#gid=0) and we have no control over what model is used under the hood (after several rounds of feedback with the AWS team, we were admitted to that it’s using Sonnet 3.0 for responses, but even after upgrading to 3.5 it’s not clear that it uses that in all cases; additionally, AWS confirmed that they would likely be never be using the most expensive frontier model, which goes against our goals)\n\t- **Use S3 to store & label converted data** - it is well integrated with Amazon Bedrock, Q Business, and common low-code tools (eg. Stack-ai, Flowise)\n3. **Improve retrieval by extracting/converting rich data to AI-friendly text-based formats, e.g.**\n\t- Rich PDFs (with graphs, charts, and tables) can be converted to Markdown (e.g. [<u>PDF to Text AI Converter</u>](https://www.notion.so/trilogy-enterprises/PDF-to-Text-AI-Converter-0ce5d008cb9e49be9911e9e60a808c7e))\n\t- Call transcripts are cleaned up by removing timestamps, reducing the input token count by 20-25%\n\t- Note: we acknowledge this function is in the path of the steamroller, but it is not being done today well by AWS solution for our use cases, and we need a stop-gap until this gets solved.\n- **Improve retrieval by annotating data with rich attributes** - improves data retrieval quality as the retrievers can defined to look up the best type of data and fall back if none is found (e.g. lookup L3 TPM TT and default to L2 C3 model, or L1 raw data)\n\t- These attributes are:\n\t\t- level (L1/2/3)\n\t\t- function (eng, tpm, etc..)\n\t\t- type (feature, architecture, stickiness)\n\t\t- status (draft, SME-reviewed, deprecated)\n\t- Important: **Build generic/reusable AI-enabled tools that produce higher-level data, using reusable 2nd Brains and Schemas**\n\t\t- e.g. an L3 PreLOI & DD specs will use L2 data (eg. architecture, requirements, features) or L1 data (interviews)\n\t\t- e.g., a generic [<u>M&A Chatbot</u>](https://www.notion.so/trilogy-enterprises/M-A-Bot-Prompt-4f945912a61741f78728302f31e68176), that leverages the [<u>Stickiness 2nd Brain</u>](https://www.notion.so/trilogy-enterprises/Product-Stickiness-Evaluation-SB-0313d2da0d704cbe899065d3dfc2529b) and the [<u>Stickiness Report Schema</u>](https://www.notion.so/trilogy-enterprises/Stickiness-Report-Schema-045d50deecbb4c4bbb61ab6a8a8ec745)\n- **Manage 2nd Brains, Schemas, and Context Packs in a centralized repository.** We choose **Notion** because\n\t1. It forces one to stick to the content and avoid wacky formatting with a bunch of complex tables and diagram images that the AI doesn't understand, as we do for example in [DD P2s](https://docs.google.com/document/d/12Zvw8CbLZfafnpvanlVa6X8q3p3ga1fAnpWnXlhUyFA/edit) and [Stickiness WUs](https://docs.google.com/document/d/1LNf44mk7cgd8AqJ4EZNd6GsoAs-Pu1idn_ClwF9UMOU/edit#heading=h.xhf94ciqnjye)\n\t2. There is a clear document hierarchy, and seeing all documents in a tree structure on the left nav bar at all times, including subpages as mandatory links in a page, pushes one to keep things organized and the docs up to date.\n\t3. Additionally, Notion supports synced content sections (e.g., a prompt that includes the SB by reference).\n\n## Architecture Diagram\n\n\n[link_preview](https://lucid.app/lucidchart/e25a69bd-ca86-45b1-b904-e26f0bd0df73/edit?beaconFlowId=388D58709EEDDE42&invitationId=inv_9fb72867-a594-439e-a459-61697833e4e8&page=VP1jSL3THxgx#)\n\n\n\n"},{"id":"69783870-cea6-4adf-be0e-afae22926884","name":"Convert Postman collection to Markdown","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"url\": \"https://ws-eng.postman.co/workspace/ProductMind~4f2b8040-ee72-4afe-92d0-b189c4dac3e9/collection/38070356-941aecfa-a192-46a6-98b0-756a76a4693f?action=share&creator=38070356\"\n}","options":{"raw":{"language":"json"}}},"url":"https://pr131.productmind.trilogy.com/convert/url"},"status":"OK","code":200,"_postman_previewlanguage":"plain","header":[{"key":"Date","value":"Fri, 22 Nov 2024 17:49:55 GMT"},{"key":"Content-Type","value":"text/markdown; charset=utf-8"},{"key":"Content-Length","value":"236829"},{"key":"Connection","value":"keep-alive"},{"key":"x-amzn-RequestId","value":"25cd8aa6-affa-4f3e-af46-6ff0f5cd0b54"},{"key":"x-amz-apigw-id","value":"BqOaLGfMoAMEA9Q="},{"key":"X-Amzn-Trace-Id","value":"Root=1-6740c440-1ab27f042561f03676dfd0d5;Sampled=1;Lineage=1:59f458cb:0"}],"cookie":[],"responseTime":null,"body":"# Project: ProductMind - API\nProductMind is a powerful knowledge management platform that automates the conversion and organization of unstructured data from various sources like Google Drive, Notion, Github, and PDF documents into a searchable, centralized knowledge base. This API provides endpoints for file conversion, data synchronization, and interaction with the knowledge base, enabling seamless integration of ProductMind's capabilities into your workflow.\n\n## Key features:\n\n- **Sync**: Ingest and refresh data for a company\n    \n- **Query**: Query and explore the knowledge base\n    \n- **Fetch**: Get data out of 3rd party systems, such as Jira or SQL schemas\n    \n- **Write**: Write data to 3rd party systems, such as Notion\n    \n- **Convert**: Automated file conversion to Markdown format (used by Sync)\n# 📁 Collection: Sync \n\n\n## End-point: Ingest data for a company\nThis endpoint triggers the synchronization process for a specific company's data. It processes provided URLs (files and folders from various data sources).\n\n### Parameters:\n\n- `company_name` (string, required): The name of the company to synchronize data for.\n    \n- `files` (string\\[\\], optional): An array of URLs to process (see the Sync intro for supported data sources or file types).\n    \n- `folders` (string\\[\\], optional): An array of URLs to process. Alternative to `files`, list of urls will be combined from both parameters.\n    \n- `product` (string, optional): Set the product name.\n    \n- `type` (string, optional): Set the data type.\n    \n- `standalone` (boolean, optional): If set to true, the knowledge base synchronization will run after the sync is complete. Default is `true`. Useful to set to `false` during subsequent batched load, with running it as `true` for the last batch\n    \n\n> **Note**: either files or folders is required. \n  \n\nAll parameters should be passed in the request body as JSON.\n\nThe response includes details on the results of the synchronization.\n\n> **Note:** This process may take some time depending on the amount of data to be synchronized.\n### Method: POST\n>```\n>https://productmind.trilogy.com/sync\n>```\n### Body (**raw**)\n\n```json\n{\n    \"company\": \"test-new-company\",\n    \"files\": [\"https://drive.google.com/drive/folders/1GJiCuTaDaMrJMxo1jIaFnPz29_04TzbL?usp=sharing\"]\n}\n```\n\n### Response: 202\n```json\nSuccessfully synced 1 items (1 added, 0 modified, 0 renamed, 0 removed, 0 skipped) for company 'test-company-name'.\n            \nProduct details:\nProduct 'test-product-name' sync summary: 1 items (1 added, 0 modified, 0 skipped), 0 errors\n```\n\n\n⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃\n\n## End-point: Remove data by URL\nRemoves from the knowledge base a previously synced Url (file/page/etc.).\n\n## Parameters\n\n- `url` - the source file URL that should be removed (e.g. a Notion page link, or a Google drive file Url)\n    \n\nSee also: \"Remove data by company and filename\"\n\n## Technical details\n\n- the related database entry gets soft deleted\n    \n- the source, markdown and metadata files get deleted in the S3 buckets\n### Method: POST\n>```\n>https://productmind.trilogy.com/remove\n>```\n### Body (**raw**)\n\n```json\n{\n  \"url\": \"https://docs.google.com/spreadsheets/d/1ae5exvUJ-xgX_sEDejACjGQNfBMaQgGArJwdIKj12Lc/edit?usp=drive_link\"\n}\n\n```\n\n### Response: 200\n```json\n{\n  \"message\": \"Content removed successfully\",\n  \"url\": \"https://drive.google.com/drive/folders/1234567890abcdefghijklmnopqrstuvwxyz\",\n  \"company_id\": \"12345678-90ab-cdef-1234-567890abcdef\",\n  \"file_name\": \"test filename\"\n}\n```\n\n\n⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃\n\n## End-point: Remove data by company and filename\nRemoves from the knowledge base a previously synced Url (file/page/etc.).\n\nSee also: \"Remove data by URL\"\n\n## Parameters\n\n- `company_name` - name of the company\n    \n- `file_name` - name of the file that should be removed (e.g. \"Product presentation.pdf\")\n    \n\n## Technical details\n\n- the related database entry gets soft deleted\n    \n- the source, markdown and metadata files get deleted in the S3 buckets\n### Method: POST\n>```\n>https://productmind.trilogy.com/remove\n>```\n### Body (**raw**)\n\n```json\n{\n  \"company\": \"test-company-name\",\n  \"file_name\": \"test sheet for TAI-36\"\n}\n\n```\n\n### Response: 200\n```json\n{\n  \"message\": \"Content removed successfully\",\n  \"url\": \"https://drive.google.com/drive/folders/1234567890abcdefghijklmnopqrstuvwxyz\",\n  \"company_id\": \"12345678-90ab-cdef-1234-567890abcdef\",\n  \"file_name\": \"test filename\"\n}\n```\n\n\n⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃\n\n## End-point: Refresh data for a company\nThis endpoint triggers the synchronization process for a specific company's data. It retrieves known URLs from the database and refreshes all changed ones and adds new files/subpages from known folders.\n\n### Parameters:\n\n- `company_name` (string, required): The name of the company to synchronize data for.\n    \n- `product` (string, optional): Limit the refresh to a specific product.\n    \n- `type` (string, optional): Limit the refresh to a specific data type.\n    \n- `standalone` (boolean, optional): If set to true, the knowledge base synchronization will run after the sync is complete. Default is `true`.\n    \n\nAll parameters should be passed in the request body as JSON.\n\nThe response includes details on the results of the synchronization.\n\n> **Note:** This process may take some time depending on the amount of data to be synchronized.\n### Method: POST\n>```\n>https://productmind.trilogy.com/sync\n>```\n### Body (**raw**)\n\n```json\n{\n  \"company\": \"test-company-name\",\n  \"product\": \"example-product\"\n}\n```\n\n### Response: 202\n```json\nSuccessfully synced 1 items (1 added, 0 modified, 0 renamed, 0 removed, 0 skipped) for company 'test-company-name'.\n            \nProduct details:\nProduct 'test-product-name' sync summary: 1 items (1 added, 0 modified, 0 skipped), 0 errors\n```\n\n\n⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃\n# 📁 Collection: Query \n\n\n## End-point: List companies\nThis endpoint retrieves a list of companies stored in the ProductMind knowledge base.\n\n### Parameters:\n\n- `command` (string, required): \\`list_companies'\n    \n\nAll parameters should be passed in the request body as JSON.\n### Method: POST\n>```\n>https://productmind.trilogy.com/list\n>```\n### Body (**raw**)\n\n```json\n{\n    \"command\": \"list_companies\"\n}\n\n```\n\n### Response: 200\n```json\n* act-on\n* centreviews\n* cirrus_insight\n* cloudhouse\n* cognitoforms\n* contently\n...\n```\n\n\n⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃\n\n## End-point: List files of a company\nThis endpoint retrieves a list of all files and folders currently stored in the ProductMind knowledge base for a specific company.\n\n### Parameters:\n- `command` (string, required): `list_files'\n- `company` (string, required): The name of the company to list files for.\n\nAll parameters should be passed in the request body as JSON.\n### Method: POST\n>```\n>https://productmind.trilogy.com/list\n>```\n### Body (**raw**)\n\n```json\n{\n    \"command\": \"list_files\",\n    \"company\": \"test-product-name\"\n}\n\n```\n\n### Response: 200\n```json\n# test-company-name\n* Notion Page\n  * [2a.1.iii - another nested test page](https://www.notion.so/2a1iii--another-nested-test-page-36948b7cd32f41e69e204abea3e74693)\n  * [2b.1 - Test page for]\n  ...\n...\n            \n```\n\n\n⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃\n\n## End-point: Query the knowledge base\nThis endpoint allows querying the ProductMind knowledge base. It provides powerful search capabilities across all converted and organized content.\n\n### Parameters:\n\n- `query` (string, required): The search query string.\n    \n- `company` (string, required): The company name for which to search.\n    \n- `product` (string, optional): Filter results by product name.\n    \n- `type` (string, optional): Filter results by data type\n    \n- `refresh` (boolean, optional): Whether to refresh the search index before querying. Default is false.\n    \n- `output` (string, optional): What to return, full \"docs\" (default) or \"chunks\"\n    \n- `return_type` (string, optional): Default to 'document'\n    \n- `results` (number, optional): Maximum number of results to return. Default is 10.\n    \n\nAll parameters should be passed in the request body as JSON.\n### Method: POST\n>```\n>https://productmind.trilogy.com/query\n>```\n### Body (**raw**)\n\n```json\n{\n  \"query\": \"What are the key features of the product?\",\n  \"company\": \"test-company-name\",\n  \"product\": \"example-product\",\n  \"type\": \"\",\n  \"refresh\": false,\n  \"output\": \"docs\",\n  \"return_type\": \"document\",\n  \"results\": 5\n}\n\n```\n\n### Response: 200\n```json\n<documents>\n  <document index=\"1\">\n    <source>test-company-name/example-product/L2/Platform APIs.md</source>\n    <url>https://ws-eng.postman.co/workspace/Platform-Prod~66ec436e-5fcd-43ad-964c-f70d5ca1225f/collection/31124709-d038145a-a2fd-46f9-8cd1-f6024afbbf72</url>\n    <document_content>\n      <![CDATA[\n</qti-prompt>\\n      <qti-simple-choice identifier=\\\"A\\\">It induced a rise in global alliances and partnerships.</qti-simple-choice>\\n      <qti-simple-choice identifier=\\\"B\\\">It heightened political tensions between East and West.</qti-simple-choice>\\n      <qti-simple-choice identifier=\\\"C\\\">It increased isolation and societal division.</qti-simple-choice>\\n      <qti-simple-choice identifier=\\\"D\\\">It led to the decline of the English Language.</qti-simple-choice>\\n    </qti-choice-interaction>\\n    <qti-media-interaction response-identifier=\\\"HELP_REQUESTED\\\" autostart=\\\"false\\\">\\n      <video controls=\\\"true\\\" data-speaker-name=\\\"John F. Kennedy\\\" data-speaker-biography-short=\\\"35th US President\\\" data-speaker-image=\\\"https://alphacoachbot-production-midjourney-images.s3.us-east-1.amazonaws.com/production/mcq6speakerImage.jpg\\\">\\nHere&apos;s what you need to know: The subdued rivalry of imperialism in the 20th century paved the way for an integrated and globalized world. With a decrease in imperialistic competition, countries had room to increase global partnerships spanning different sectors like economies, cultures, and politics.        <source src=\\\"https://alphacoachbot-production-midjourney-images.s3.us-east-1.amazonaws.com/production/mcq6Video.mp4\\\" type=\\\"video/mp4\\\"/>\\n      </video>\\n    </qti-media-interaction>\\n  </qti-item-body>\\n  <qti-response-processing template=\\\"https://purl.imsglobal.org/spec/qti/v3p0/rptemplates/match_correct\\\"/>\\n</qti-assessment-item>\\n\",\n\"clusterId\": \"AP World Topic 9.6\",\n\"clusterDescription\": \"Globalized Culture After 1900\",\n\"attributes\": []\n}\n]\n}\n}\n```\n⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃\n## End-point: getDMChatHistory\nThis endpoint allows to get chat history that student made with a key figure. Uses pagination with 50 item per page.\n## Input\ninput object with below parameters:\n- `keyFigureName` (string, required) Name of the key figure. `getHistoricalFigures` query can be used to retrieve key figure names.\n- `generatedContentId` (string) Content ID if you want to retrieve chat history for specific content.\n- `page` (integer) Page number to retrieve, starts from zero.\n## Output\nThe output is an object with the following attributes:\n- `hasNextPage` (boolean): Indicates if there is next page to retrieve.\n- `chatHistory` (list): Contains list of object with following fields\n- `message` (string): Message content\n- `senderUserId` (string): The user ID of the sender\n- `timestamp` (string): The iso formatted timestamp of message sent\n- `platformGeneratedContentID` (string): generatedContentId if conversation belongs to specific content\n### Method: POST\n>```\n>{{GRAPHQL_URL}}\n>```\n### Headers\n      ]]>\n    </document_content>\n  </document>\n  <document index=\"2\">\n    <source>test-company-name/example-product/Copy of Features summary.md</source>\n    <url>https://drive.google.com/file/d/1k_TEXdtY6eR7QADDuti86audfwRwKxm58u7BTj01pJU/view?usp=sharing</url>\n    <document_content>\n      <![CDATA[\n# Copy of Features summary\n## Sheet1\n| Feature | Description |\n| - | - |\n| Coolness | The product is really cool |\n\n      ]]>\n    </document_content>\n  </document>\n  <document index=\"3\">\n    <source>test-company-name/example-product/Features summary.md</source>\n    <url>https://drive.google.com/file/d/1VPtcMjO5x_JjS0btYKxJMM_tHcVO3ryo_BfPKO26jPU/view?usp=sharing</url>\n    <document_content>\n      <![CDATA[\n# Features summary\n## Sheet1\n| Feature | Description |\n| - | - |\n| Coolness | The product is really cool |\n\n      ]]>\n    </document_content>\n  </document>\n  <document index=\"4\">\n    <source>test-company-name/example-product/Copy of Cool Feature description.md</source>\n    <url>https://drive.google.com/file/d/1jP80-UcTfiUkt2NIr4MYWBxQ18EqgVAeTx3wxRxWN-4/view?usp=sharing</url>\n    <document_content>\n      <![CDATA[\n# Cool Feature description\nLorem ipsum….\n      ]]>\n    </document_content>\n  </document>\n  <document index=\"5\">\n    <source>test-company-name/example-product/Cool Feature description.md</source>\n    <url>https://drive.google.com/file/d/1A3oxDcaolfIHINCuQZA9EkZ31_8KJT2WeXWUX0z8tbA/view?usp=sharing</url>\n    <document_content>\n      <![CDATA[\n# Cool Feature description\nLorem ipsum….\n      ]]>\n    </document_content>\n  </document>\n</documents>\n            \n```\n\n\n⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃\n# 📁 Collection: Fetch \n\n\n## End-point: Fetch Jira tickets\nThis endpoint retrieves Jira tickets based on the provided query parameters. It allows users to fetch ticket information from Jira and returns the data in a structured format.\n\n### Parameters:\n- `tickets` (string[], required): List of Jira ticket IDs to fetch.\n- `export_sub_tasks` (boolean, optional): Controls whether to include also subtasks. Default is true.\n\nAll parameters should be passed in the request body as JSON.\n### Method: POST\n>```\n>https://productmind.trilogy.com/fetch/jira-tickets\n>```\n### Body (**raw**)\n\n```json\n{\n  \"tickets\": [\"TAI-34\", \"TAI-36\"]\n}\n```\n\n### Response: 200\n```json\n[\n  {\n    \"key\": \"TAI-34\",\n    \"summary\": \"Create friendly names for all of our APIs\",\n    \"product\": \"Trilogy: Gen AI - ProductMind\",\n    \"description\": \"The base domain should be \\\\*.productmind.trilogy.com\\n\\n...\",\n    \"output\": \"# CHANGELOG...\"\n  },\n  {\n    \"key\": \"TAI-36\",\n    \"summary\": \"Add support for importing API documentation from Postman\",\n    \"product\": \"Trilogy: Gen AI - ProductMind\",\n    \"description\": \"...\",\n    \"output\": \"# CHANGELOG...\"\n  }\n]\n```\n\n\n⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃\n\n## End-point: Fetch SQL Schema\nThis endpoint retrieves the SQL schema for a specified database. It allows users to fetch table structures, column definitions, and relationships, providing a comprehensive view of the database schema.\n\n### Parameters:\n- `user` (string, required): The username for database authentication.\n- `password` (string, required): The password for database authentication.\n- `hostname` (string, required): The hostname of the database server.\n- `database` (string, required): The name or identifier of the database for which to fetch the schema.\n- `tables` (string[], optional): An array of specific table names to fetch. If not provided, the schema for all tables will be returned.\n- `modules` (string[], optional): An array of specific modules to include in the schema.\n- `skip_cleanup` (boolean, optional): Whether to skip cleanup operations after fetching the schema. Default is false.\n\nAll parameters should be passed in the request body as JSON.\n### Method: POST\n>```\n>https://productmind.trilogy.com/fetch/sql-schema\n>```\n### Body (**raw**)\n\n```json\n{\n    \"user\": \"db_user\",\n    \"password\": \"secure_password\",\n    \"hostname\": \"db.hostname.com\",\n    \"database\": \"sample_database\",\n    \"tables\": [\"table1\", \"table2\", \"table3\"],\n    \"modules\": [\"module1\", \"module2\"],\n    \"skip_cleanup\": true\n}\n\n```\n\n### Response: 200\n```json\n# TABLE grades - Models grades academic courses are taught in. <module=skill_stack><module=curriculum>\nCREATE TABLE grades (\nid char(36) NOT NULL DEFAULT (uuid()) COMMENT 'uuid',\ngrade enum('PK','K','1','2','3','4','5','6','7','8','9','10','11','12','AP') NOT NULL COMMENT 'Grade that can be associated with the academic course.',\nname varchar(255) NOT NULL COMMENT 'Display name for the grade, e.g. Level 100 for 1st Grade.',\n```\n\n\n⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃\n# 📁 Collection: Write \n\n\n## End-point: Create a Notion page from Markdown content\nThis endpoint allows writing content to Notion pages, creating a new page.\n\n### Parameters:\n\n- `command` (string, required): The operation to perform. Should be \"create\".\n    \n- `parent_page_id` (string, required): The ID of the parent page when creating a new page.\n    \n- `content` (string, required): The Markdown content to be written to the page.\n    \n- `title` (string, optional): The title for the newly created page. If missing it will be generated from the content automatically.\n    \n\nAll parameters should be passed in the request body as JSON.\n### Method: POST\n>```\n>https://productmind.trilogy.com/write/notion\n>```\n### Body (**raw**)\n\n```json\n{\n  \"command\": \"create\",\n  \"parent_page_id\": \"c4023ec59a854c0988fbdf9169d9364e\",\n  \"content\": \"# New Page\\n\\nThis is a new page created via the API.\\nWith some bullets:\\n- bullet 1\\n- bullet 2\\n- bullet 3\",\n  \"title\": \"API Created Page\"\n}\n```\n\n### Response: 200\n```json\n{\n  \"page_id\": \"0987654321fedcba0987654321fedcba\",\n  \"page_url\": \"https://www.notion.so/My-New-Page-0987654321fedcba0987654321fedcba\"\n}\n```\n\n\n⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃\n\n## End-point: Append Markdown content to a Notion page\nThis endpoint allows writing content to Notion pages, appending content to an existing page.\n\n### Parameters:\n\n- `command` (string, required): The operation to perform. Should be \"append\".\n    \n- `page_id` (string, required): The ID of the target Notion page.\n    \n- `content` (string, required): The Markdown content to be added to the page.\n    \n- `title` (string, optional): The title to replace the existing page title. When skipped the title is not changed.\n    \n\nAll parameters should be passed in the request body as JSON.\n### Method: POST\n>```\n>https://productmind.trilogy.com/write/notion\n>```\n### Body (**raw**)\n\n```json\n{\n  \"command\": \"append\",\n  \"page_id\": \"3307018d-d8c2-43e4-9419-4c28b0c16678\",\n  \"content\": \"Adding some more content to this page.\\nLet's try a numbered list:\\n1. First item\\n2. Second item\\n3. Third item\"\n}\n```\n\n### Response: 200\n```json\n{\n  \"page_id\": \"0987654321fedcba0987654321fedcba\",\n  \"page_url\": \"https://www.notion.so/My-New-Page-0987654321fedcba0987654321fedcba\"\n}\n```\n\n\n⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃\n\n## End-point: Replace content of a Notion Page from Markdown\nThis endpoint allows writing content to Notion pages, replacing the content of an existing page.\n\n### Parameters:\n\n- `command` (string, required): The operation to perform. Should be \"replace\".\n    \n- `page_id` (string, required): The ID of the target Notion page.\n    \n- `content` (string, required): The Markdown content to be written to the page.\n    \n- `title` (string, optional): The title to replace the existing page title. When skipped the title is not changed.\n    \n\nAll parameters should be passed in the request body as JSON.\n\n> Note: this operation is slow because of technical details of the Notion API. Creating a new page or appending to an existing is much more preferred.\n### Method: POST\n>```\n>https://productmind.trilogy.com/write/notion\n>```\n### Body (**raw**)\n\n```json\n{\n  \"command\": \"replace\",\n  \"page_id\": \"3307018dd8c243e494194c28b0c16678\",\n  \"content\": \"# This is an updated Page\\n\\nThis is a page with content replaced via the API.\\n\\nWith some bullets:\\n- bullet 1\\n- bullet 2\\n- bullet 3\",\n  \"title\": \"API Created Page with a changed title\"\n}\n```\n\n### Response: 200\n```json\n{\n  \"page_id\": \"0987654321fedcba0987654321fedcba\",\n  \"page_url\": \"https://www.notion.so/My-New-Page-0987654321fedcba0987654321fedcba\"\n}\n```\n\n\n⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃\n# 📁 Collection: Convert \n\n\n## End-point: Convert to Markdown\nThis is a generic endpoint that allows converting any supported file types and file sources to Markdown format.\n\nIt is basically an aggregation of the other Convert methods (the proper one is selected based on the url and used under the hood).\n\n### Parameters:\n\n- `url` (string, required): The URL of the PDF file stored in Google Drive to be converted.\n    \n- `force_reprocess` (boolean, optional): Indicates whether processing should happen even if the results are already cached. Note that this is not currently supported for all file types. **Default**: false\n    \n- `return_mode`(enum, optional): Indicates how the results should be returned:\n    \n    - `md`: Return the contents (the markdown after conversion)\n        \n    - `s3_url`: Return an S3 url pointing to a file that contains the contens (useful for automations passing content around)\n        \n    - `auto`(default): Normally returns the results as markdown - there is a special case for large PDFs that get returned as an `s3_url` above a treshold.\n        \n\nAll parameters should be passed in the request body as JSON.\n\n### Supported data sources and file formats\n\nℹ️ See notes on permissions below\n\n#### Google drive\n\n- PDF\n    \n- Google doc\n    \n- Google sheet\n    \n- Word (.docx)\n    \n- Excel (.xlsx)\n    \n- Markdown (.md)\n    \n- Plain text (.text)\n    \n- YAML (.yml or .yaml)\n    \n- MP4\n    \n    - With transcript next to it or without. See note below for details\n        \n\n#### **Notion**\n\n- Notion pages\n    \n\n#### **Postman**\n\n- Postman collection\n    \n- Postman folder\n    \n\n#### GitHub\n\n- Markdown (.md)\n    \n- YAML (.yml or .yaml)\n    \n- Plain text (.txt)\n    \n\n### Important information for data sources\n\n#### Google drive\n\n> **Note:** The Google Drive file must be shared with the `cpm-diligence@trilogy.com` group for this endpoint to access and process it. \n  \n\n##### Videos with transcripts\n\n> **Note on permissions:**  \n\\- In order to check and find a transcript file in Google drive next to the video the [cpm-diligence@trilogy.com](https://mailto:cpm-diligence@trilogy.com) service account needs to have view access to the folder containing the video and transcript (otherwise we can't check whether there is another file next to the video) \n  \n\n\\- In order to transcribe a video the [cpm-diligence@trilogy.com](https://mailto:cpm-diligence@trilogy.com) service account needs to have access to it, and the video needs to allow viewers to download the video (you can change this on the share dialog under the settings clicking the cog icon). This is sometimes for meeting recordings off by default.\n\n#### Notion\n\n> **Note:** The Notion page must be shared with the ProductMind-Export-Import integration for this endpoint to access and process it.  \nTo share the page with the exporter, follow these steps:  \n1\\. Open the page in Notion.  \n2\\. Open the 'three dots' menu in the top-right corner.  \n3\\. Ensure that 'ProductMind-Export-Import' is listed under 'Connections'. If not, add it. \n  \n\n#### Postman\n\n> **Note**: The following URL formats are supported for Postman collections:  \n\\- Workspace folder: [https://ws-eng.postman.co/workspace/Platform-Prod~66ec436e-5fcd-43ad-964c-f70d5ca1225f/folder/31124709-c9060ee9-6b7c-4d32-861c-7ff22d5d9c60](https://ws-eng.postman.co/workspace/Platform-Prod%5C~66ec436e-5fcd-43ad-964c-f70d5ca1225f/folder/31124709-c9060ee9-6b7c-4d32-861c-7ff22d5d9c60)  \n\\- Collection: [https://ws-eng.postman.co/workspace/ProductMind~4f2b8040-ee72-4afe-92d0-b189c4dac3e9/collection/38070356-941aecfa-a192-46a6-98b0-756a76a4693f?action=share&amp;creator=38070356](https://ws-eng.postman.co/workspace/ProductMind%5C~4f2b8040-ee72-4afe-92d0-b189c4dac3e9/collection/38070356-941aecfa-a192-46a6-98b0-756a76a4693f?action=share&creator=38070356)  \n\\- Workspace folder (alternative format): [https://ws-eng.postman.co/workspace/ProductMind~4f2b8040-ee72-4afe-92d0-b189c4dac3e9/folder/38070356-b86b8070-d4d8-44b4-9361-c47d3e2256b2?action=share&amp;source=copy-link&amp;creator=38070356&amp;ctx=documentation](https://ws-eng.postman.co/workspace/ProductMind%5C~4f2b8040-ee72-4afe-92d0-b189c4dac3e9/folder/38070356-b86b8070-d4d8-44b4-9361-c47d3e2256b2?action=share&source=copy-link&creator=38070356&ctx=documentation)  \n\\- Collection (alternative format): [https://ws-eng.postman.co/workspace/Platform-Prod~66ec436e-5fcd-43ad-964c-f70d5ca1225f/collection/31124709-d038145a-a2fd-46f9-8cd1-f6024afbbf72](https://ws-eng.postman.co/workspace/Platform-Prod%5C~66ec436e-5fcd-43ad-964c-f70d5ca1225f/collection/31124709-d038145a-a2fd-46f9-8cd1-f6024afbbf72) - Workspace folder (without workspace name): [https://ws-eng.postman.co/workspace/4f2b8040-ee72-4afe-92d0-b189c4dac3e9/folder/38070356-5f19b4dd-c3e9-48cd-9383-7d4d030f74ed?action=share&amp;source=copy-link&amp;creator=38070356&amp;ctx=documentation](https://ws-eng.postman.co/workspace/4f2b8040-ee72-4afe-92d0-b189c4dac3e9/folder/38070356-5f19b4dd-c3e9-48cd-9383-7d4d030f74ed?action=share&source=copy-link&creator=38070356&ctx=documentation)\n### Method: POST\n>```\n>https://pr131.productmind.trilogy.com/convert/url\n>```\n### Body (**raw**)\n\n```json\n{\n  \"url\": \"https://drive.google.com/file/d/1WKLsFJJn9jwWSkHb_E-kUBllPpAg76ua/view?usp=drive_link\"\n}\n```\n\n### Response: 200\n```json\n# Page 1\n\n# Contently Creation Features\n\n## G2's #1 Rated Enterprise Content Creation Technology\n\nBuild a team of elite creators with Contently and start creating the content of your dreams. See how our advanced content marketing platform can help you tell stories that engage your audience and drive results.\n\n[TAKE A PRODUCT TOUR >>](#)\n\n## Intelligent Talent Recommendations\n\nBuild a team of award-winning content creators that are perfect for your content program with the help of our Intelligent Talent Recommendation algorithm.\n\nWe match you with the perfect freelancers based on your content strategy so can start telling incredible stories together.\n\n[Schedule a custom demo](#)\n\n[Screenshot of Contently's talent search interface showing a list of talent recommendations on the left side and detailed contributor information on the right. The interface displays various content creators with their profile pictures, recent stories, and last active dates. The layout is clean and organized with clear sections for contributors, details, and invite status.]\n\nContently Creation Features | 1\n\n# Page 2\n\n# Content and Multimedia Editors\n\nCreate content quickly and easily with our content and multimedia editors. Track activity, build custom workflows, and collaborate easily with comment functionality across written content, visual, and video content.\n\nGet a summary of the brief, target audience, and strategy of each story so everyone stays on the same page.\n\n# Automated Content Optimization and Governance\n\nAutomate your content creation checklist with advanced tools that check your content for plagiarism, SEO, reading time, reading level, grammatical issues, and more.\n\nIt's like having editorial superpowers.\n\n[Screenshot of a content editor interface showing an article titled \"3 Problems That Plague Fintech Case Studies\". The interface displays various content optimization tools and metrics including reading time, character count, and readability scores. The editor has a clean, modern design with editing and sharing options.]\n\n# Voice and Tone Analyzer\n\nBring science to the art of brand voice with our Tone Analyzer, powered by IBM Watson.\n\nSee which voice and tone traits engages your audience the most, and then optimize your content to hit the perfect note with real-time analysis\n\nContently Creation Features 2\n\n# Page 3\n\nThe image shows a web interface for what appears to be a content creation platform focused on fintech case studies. The interface displays:\n\n# The Problems With Fintech Case Studies [And How to Fix Them in 2022]\n\nThe page shows a content editor with several sections:\n\n- A main text editing area containing an article about fintech case studies\n- A right sidebar with various content optimization metrics including:\n  - Quality indicators\n  - Optimization scores\n  - Style and tone measurements showing sliders for:\n    - Openness\n    - Conscientiousness \n    - Extraversion\n    - Agreeableness\n    - Emotional range\n\nThe interface has a clean, modern design with a light color scheme and appears to be a specialized content creation tool that helps writers optimize their fintech case study content with AI-powered recommendations and analysis.\n\nAt the bottom of the image, there's a page number indicator showing \"Contently Creation Features 3\"\n\nThe tool seems designed to help content creators write more effective and engaging case studies while maintaining consistent tone and style guidelines.\n```\n\n### Response: 200\n```json\ns3://productmind-convert-to-md/pdf/8277eb4f9db16c0727cfbafd0a3cd009_1_full.md\n```\n\n### Response: 200\n```json\n# Test gdoc6\n\n# This is an example document that we want to convert to MD\n\n## With a subtitle that is changed now\n\nHe*re is some formatting. **Of this** stuff.* **Bold** and underlined,  \nAnd colors\\!\\!\\!\n\nHere a table\n\n| aaad | frefer | ewfrarfwfr |\n| :---- | :---- | :---- |\n| fasaer | Aerhjeraf aerfhkjaerf | Kllkmklare aerfknleavr |\n\n# A header\n\n## A subheader\n\n### And one more level down \\-2\n\nAnd some text aligned in a few ways  \nLorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent luctus scelerisque finibus. Sed dignissim mauris bibendum enim elementum commodo. Fusce eget ante enim. Sed magna libero, sagittis quis tincidunt nec, mollis quis nisi. In non tempor diam. Fusce consectetur ultrices feugiat. Vestibulum posuere felis sit amet ex ullamcorper, et cursus orci scelerisque.\n\nPraesent mauris nibh, ultricies sit amet rutrum ut, porttitor eget eros. Donec eget nulla mattis, lobortis risus in, sollicitudin nulla. Aenean fringilla nunc nibh, in elementum libero tristique non. Mauris eget quam eleifend, sagittis enim sed, tempor sapien. Donec porttitor consectetur arcu, eu pulvinar orci fermentum vitae. Ut id commodo velit, eget accumsan tortor. Sed lectus nulla, finibus et ex ut, tempor blandit libero.\n\nPellentesque nec lacus pulvinar, dictum augue at, mattis nisl. Vivamus feugiat, lacus eget sodales commodo, urna tortor vulputate purus, eu varius enim m\n\nA numbered list:\n\n1. Item 1  \n2. Item 2  \n3. Afdkjnkdlfnsv  \n4. Knmknkmlkl\n\nA bulleted list:\n\n- Njjaerfaerf  \n- Kklaerf kaerrfko jelrfk: fearfefref  \n- Kemrfklaef\n\n\n  \nTesting some Hungarian: árvíztűrő tükörfúrógép \n```\n\n### Response: 200\n```json\n# Just a test sheet\n\n## First sheet\n\ncolumne 1\n\n## priorities\n\n\n\n| Feature | Category | Status | Owner | Size | Launch | Notes |\n| --- | --- | --- | --- | --- | --- | --- |\n| abbavecr | Category 1 | Not started |  | XS | Q1 |  |\n| klklkj aferkjh | Category 2 | In progress |  | S | Q2 |  |\n| kkds | Category 3 | Blocked |  | M | Q3 |  |\n| dsjajknasd | Category 4 | Launched |  | L | Q4 |  |\n\n\n\njk\n\n\n```\n\n### Response: 200\n```json\n# Copy of Follow-up questions - Interviewstream_IVSAnswersv2\n\n# Follow-up questions \\- Interviewstream\n\n1. **Pricing**  \n   1. What do customers purchase in terms of units, both education and non-education?\n\n      *For education, our understanding is that customers purchase a certain number of interviews which is estimated based on the current number of FTEs for that district (as opposed to the number of FTEs they plan to hire).*   \n      \n\n   *The majority of US education customers\\* purchase a license w/unlimited interviews. Pricing/costs are based on FTE’s, which is also how their ATS systems and hiring systems set costs typically. The rationale for FTE-basis, outside of this is pricing they are used to, is that you can assume a minimum of 20-25% FTE turnover annually (teacher turnover is \\~30% annually in the US). Pricing tiers are set with each partner (i.e. Powerschool, Frontline) based on FTE ranges with custom pricing for “the largest” school districts.  Essentially- the FTE is a proxy for total interviews expected to be held annually.*   \n     \n   *Canadian schools are a bit different w/conversion in costs/hiring/maturity of market in technology use. Our partner pricing table with applytoeducation is based on a % of their total spend with applytoeducation on hiring related products (i.e. ATS, job boards). This is also an unlimited license just worth noting that the way we determine pricing is different (ATE does use a base of FTE for their pricing so ultimately the construct is similar).  Prior to this partnership starting in 2023, Canadian schools were priced based on FTE once US education pricing was updated in 2022\\.*   \n     \n   *\\*There are some exceptions, not in the majority, of education clients who either (a) signed a long-term contract prior to 2022 where pricing was changed as noted above, or (b) that are not with partners and/or due to budget constraints needed a lower cost.  For those that signed long term contracts prior to 2022, they are on unlimited licenses based on pricing set from prior revenue team and once contract is renewing, we re-establish pricing. For those districts that needed lower costs and signed post 2022, we will then apply interview limits to their contract.  Any exceptions are outlined in the contracts/order forms and are reviewed in a similar manner with the account as noted below for non-education clients.*\n\n        \n      *For non-education, our understanding is that customers purchase a certain number of interviews which is estimated based on the number of interviews expected or the number of scheduled events.*  \n      \n\n   *That is correct, the majority of non-education clients that are under $20,000 in ARR have set limits for their on demand interviews held or scheduled events sent. Over $20,000, which is NOT many accounts, have unlimited licenses. As noted above, there are a handful of exceptions to this however again, it is a legacy account or a specifically outlined part of the annual contract.* \n\n   2. Confirm or correct the following understanding:  \n      *Customers purchase X number of interviews for 1 year (or multi years).*  \n      *If they use it all up, an upsell is discussed with customers. If they do not use it, nothing happens, i.e. customers are not refunded.*   \n      \n\n   *Correct re: upsell. During QBRs, usage is discussed.  If a client is approaching the limit, they have an option to pay for the annual overuse as a 1x fee at the same rate per interview OR “buy up” to another tier.*   \n     \n   *Correct re: refunds. If limits are not reached, there is no refund. Limits are worded as “up to X interviews held/etc in an annual term.”*\n\n        \n      *What happens if they go over without renegotiating \\- do you just sell them additional usage at the same base rate?*   \n      \n\n   *See above, yes.  Note- this is uncommon.  In all recent situations where usage limits have been exceeded, client has renegotiated to a different tier of pricing during quarterly or upcoming annual term.* \n\n2. **Cost savings**  \n   1. Can you quantify productivity increase when customers use interviewstream?\n\n      *You mentioned that customers measure ROI as “time saved”. We would like to understand from a typical customer example, how much time was saved (ideally separately for education and non-education). E.g., for much back-and-forth on email/phone, a recruiter saves when using the scheduler, and how many such events a recruiter typically has in a month.*  \n      \n\n   *Please see additional attachments for a few sample “real” ROI calculators provided based on prospect/customer conversations.*  \n\n        \n   2. In case actual cost savings/offsets are coming from interviewstream, if you are aware of such an example, can you please quantify them and state if the cost (budget item) was reduced? E.g. for Education,since principals are the interviewers, we imagine it only translates into a soft cost-saving (represented by a productivity boost in the principal’s time), while for large enterprises with multiple recruiters, the time saved across scheduling and syncing interview could accrue to be big enough to save a full recruiting FTE (related question \\- how big would the company have to be/pay for the product for this to be true)\n\n   *Please see ROI calculators for estimated savings.  At this time, it is not common for clients to share the “final savings” however some are noted in our case studies which can be found here- [https://interviewstream.com/resources/case-studies/](https://interviewstream.com/resources/case-studies/)* \n\n   \n\n   *To date, I have rarely seen a company with at least 100 employees not see significant potential ROI by deploying on demand and/or scheduler.*\n\n      \n\n3. **Product deployment**  \n   1. Can you describe the typical deployment process for larger customers, step-by-step?\n\n   *Here is the typical implementation timeline provided to a larger customer. As discussed live, the timeline may be adjusted once discussed or if an integration is more “custom” overall.*\n\n      \n\n| Implementation Timeline |  |\n| ----- | ----- |\n| Description | Estimated Timeline |\n| Kick off meeting to discuss timelines, business objectives, expectations IT requirements / documentation / whitelisting | Week 1 |\n| Configuration of interviewstream platform settings and integration Client platform branding, integration setup continued  | Week 2-3 |\n| Platform training and workflow creation  | Weeks 4-6 |\n| User acceptance testing Go-live in production  | Weeks 7-9 |\n\n      \n\n2. What is the required time for deployment of a fully-fledged product? Measured in hours or days of active work by professional services, support, or engineering. And please mention how many people are typically involved. \n\n   \n\n   *For a stand-alone or standard integration client, the product can be fully deployed within less than a day, however most clients still follow a timeline similar to the the implementation timeline above given internal trainings/etc.* \n\n   \n\n   *Unless custom\\*, the primary person deploying/implementing an account at interviewstream is the Customer Success Manager (CSM).  Implementing an account in interviewstream takes at most a few hours of their time. Requests for customization/branding/importing data from prior system/etc. from the client may extend this time frame, however training and conversations with the client are the bulk of the CSMs time during the implementation process.* \n\n   \n\n   *\\*If custom or unique, which is rare, our CTO or VP, Client Services may get involved for a few hours of brainstorming. The product does not require technical involvement in implementation unless there is something custom overall.  If clients have a custom install that goes beyond a few hours of meetings and follow ups, we scope the work with them and charge additional one-time fees (this is incredibly rare).* \n\n   \n\n   3. Are there usually specific integrations required (e.g. ATS)? If yes, are these integrations fully custom (i.e. if customer churns, that custom work is completely gone and would need to be done from scratch)?  \n      \n\n   *As noted in the customer file already provided, the majority of our clients are integration in some fashion. The majority are not “custom” but are proprietary to interviewstream. A few are exclusive partnerships- i.e. Frontline and applytoeducation- and others i.e. Workday, SAP, Taleo are more complex and unique to the client. The handful of OpenAPI or custom integrations are completely unique to the clients involved.*  \n     \n   *If the customer churns and wanted to move over to a new system, they would have to work with their new partner to establish an integration independent of the above and yes, the work would have to be done by the new partner or client.* \n\n4. **Competitive landscape**  \n   1. What makes interviewstream more competitive in the Education segment? What is unique about the product that competitors do not have? Please list all competitive advantages and elaborate on them.  \n      \n\n   *The core differentiators for interviewstream in the education segment can be found on [this page](https://interviewstream.com/industries/k12/) are as follows.  interviewstream has:*  \n- *Partnerships and embedded integrations with all key ATS systems used by US and Canadian K-12 school districts/boards today:*   \n  * *Exclusive partnership and uniquely embedded integration with Frontline Education (ATS), one of the two leading ATS systems in the US K-12 market today*  \n  * *Exclusive partnership and integration with applytoeducation, the leading ATS in Canada, with market share in over 90% of Canadian school boards*  \n  * *Partnership and a strong integration to PowerSchool, the second leading ATS system in the US K-12 market today*  \n  * *And if a district is not using any of the above, a strong OpenAPI and Chrome extension option in place*  \n- *Intentional application of AI and analysis in our technology tied to creating efficiencies, without potentially introducing bias or decision direction*  \n  * [*AI Question Assist*](https://interviewstream.com/resources/blog/new-features-from-interviewstream/)*, [Recruit Assist](https://interviewstream.com/ai-recruiting-assistant/), and soon to be launched, Simple Summary*  \n  * *interview insights which applies over 10 years of data to benchmark and improve your hiring process, using millions of interviews worth of data to determine ways to improve the process and recommend*   \n- *Enhanced information security and compliance processes and certifications with K-12 in mind*  \n  * *SOC 2 Type 2, GDPR/PIPEDA data privacy/compliance*  \n  * *Deep experience working with school district teams to handle DPA’s and PIA’s for districts/boards*  \n  * *Ability to create workflows in interviewstream to support highly compliant hiring processes*  \n- *20 years of experience in K-12*   \n  * *Unique workflows designed for and with our K-12 districts and boards including specific templates for onboarding new teachers and administrators and preset templates curated for K-12’s specific use cases.*  \n  * *Customer success team members with over 10 years of experience in deploying and enhancing hiring processes in partnership with districts and boards*  \n      \n  2. For the Scheduler, is there an advanced feature (or features) that competitors (direct competitors or indirect competitors like Calendly) do not have? If yes, please elaborate on that feature.   \n     \n\n  *advanced scheduler has many great features and is a very competitively priced tool however the two features discussed that is important to our clients when considering options is (1) highly customizable landing pages and (2) automatic assignment of an agent/team member to an open slot in a complex scheduling event (i.e. multi-location, multiple potential team members to fill the slot, variable time slots). This will be much easier to understand in a live demo.  More high level information about advanced scheduler can be found [on this page](https://interviewstream.com/interview-scheduler-advanced/) and [in this article](https://interviewstream.com/resources/blog/interview-scheduling/).* \n\n       \n  3. For the Interview Builder, is there an advanced feature (or features) that competitors do not have? If yes, please elaborate on that feature.\n\n\n*interview builder, as noted previously, is a stand-alone product that has 3 active*   \n*clients.  There are two primary differentiators from competitive products- (1) there*   \n*is a strong curriculum program (HireBar) for hiring training tied to this platform*   \n*license that can be used to certify an organization’s team and (2) interview*   \n*guides built can be customized and downloaded in a variety of formats for*   \n*distribution to disparately located teams.* \n\n*The majority of interview builder’s key features can be found in our platform*  \n*through the question library and core on demand solution and in the new feature,*   \n*AI Question Assist.*\n\n*We do not actively seek new clients or present this as a primary new business*   \n*Solution, however it is a key solution, requiring limited maintenance for the 3*   \n*clients actively using it.* \n```\n\n### Response: 200\n```json\n# Demo excel file\n\n## prios\n\n\n\n| Feature | Category | Status | Owner | Size | Launch | Notes |\n| --- | --- | --- | --- | --- | --- | --- |\n| abbavecr | Category 1 | Not started |  | XS | Q1 |  |\n| klklkj aferkjh | Category 2 | In progress |  | S | Q2 |  |\n| fgg | Category 3 | Blocked |  | M | Q3 |  |\n| gggghhg | Category 4 | Launched |  | L | Q4 |  |\n\n\n\n\n```\n\n### Response: 200\n```json\n\n\n| Author | Akos Orban |  |  |\n| :---- | ----- | :---- | :---- |\n| **Product** | Trilogy: Gen AI-\\>ProductMind |  |  |\n| **Unit** | **[TAI-25](https://ws-lambda.atlassian.net/browse/TAI-25)** |  |  |\n| **Problem \u000bStatement** | **What**: |  | Sync is not picking up new documents |\n|  | **When and Where**: |  | For some notion pages children are not picked up during synchronization |\n| **Why Why Analysis** |  | **Question**: | Why are some children pages missing? |\n|  |  | **Answer**: | Because they are not getting synced in the updateCompaniesAndSync  state machine |\n|  |  | **Evidence**: | Example execution: ![][image1] |\n|  |  | **Question**: | Why are they not picked up in the recurring sync? |\n|  |  | **Answer**: | Because they are not picked up in the syncAndConvertFoldersAndFiles state machine |\n|  |  | **Evidence**: | The state machine is executed with only 2 notion pages (expecting 3\\) ![][image2] |\n|  |  | **Question**: | Why is the state machine not picking up the missing page? |\n|  |  | **Answer**: | The listing subpages lambda returns only the 2 pages it got as input. |\n|  |  | **Evidence**: | ![][image3] |\n|  |  | **Question**: | Why is the list subpages lambda not finding the 3rd subpage? |\n|  |  | **Answer**: | Because the get\\_nested\\_pages in (functions/pythonLambdas/lib/services/notion/notion_service.py) doesn’t find the subpages of the root notion page |\n|  |  | **Evidence**: | ![][image4] |\n|  |  | **Question**: | Why the get\\_nested\\_pages doesn’t return the subpages? |\n|  |  | **Answer**: | Because the function iterates through the page content to find the content block with the subpages links, but only in the first 100 returned blocks because the result from Notion API is paginated. As this page is long the matching block would be later and would need to be fetched as the next page of results. |\n|  |  | **Evidence**: | ![][image5] |\n| **Root Cause** | Since Notion API doesn’t provide a great way to get the subpages the current implementation iterates through the whole page content to find the subpages links, which are at the end of the pages. But it doesn’t take into account paginated page content response from Notion API and only checks the first 100 blocks. On a long page this is not enough. |  |  |\n| **Related \u000bTech Debt** | no |  |  |\n| **Fix** | Will need to keep loading next pages with the content until we reach the end to find all subpage links. Ideally Notion would provide a simple API for this use-case, but some research indicates that such API doesn’t exist. |  |  |\n| **Process\u000bInsights** | Need to test solution with long contents also as that could cause some pagination issues as here (maybe some timeouts or slow-downs in other cases) |  |  |\n| **Lessons Learned** | Notion API is not very useful, need to be careful with operations using it and make sure to test for edge cases. |  |  |\n\n\n\n```\n\n### Response: 200\n```json\nThis is just an example text doc\n\n\n\nLorem ipsum dolor sit amet\nLorem ipsum dolor sit amet\n\nLorem ipsum dolor sit amet\n\nLorem ipsum dolor sit amet\n```\n\n### Response: 200\n```json\nopenapi: 3.0.3\ninfo:\n  title: Subscription management API\n  version: 0.4.0\n  description: \"It's necessary to [generate a JWT Token](https://rapid-engineering.atlassian.net/wiki/spaces/SI/pages/1938358285/Generate+JWT+token) and use it as authorization method in the api.\"\n  license:\n    name: Copyright\n  contact:\n    email: rp-si@trilogy.com\n    name: RP Sales Infrastructure\nservers:\n  - url: /api/v1\n  - url: /test/api/v1\ntags:\n  - name: Customer\n  - name: Product catalog\n  - name: Subscription\n  - name: Report Usage\n  - name: Integration internal\n  - name: Invoices\n  - name: UI customer\n  - name: UI storage\n  - name: UI subscription\npaths:\n  /subscriptions:\n    get:\n      summary: Get Customer Subscriptions\n      operationId: getCustomerSubscriptions\n      description: |-\n        Retrieve subscription list filtered by parameters and by productVariantCode and productFamilyCode (pfc and pvc) set in authentication token.\n        Subscriptions can also be filtered by subscription status, e.g. Active, Pending_Activation. \n\n        A validation check for customer id present in JWT Token will be performed to prevent customers from fetching subscriptions of other customers.\n      parameters:\n        - schema:\n            type: string\n          in: query\n          name: customerId\n          description: Required for non-customer (Admin) token\n        - schema:\n            type: array\n            items:\n              $ref: '#/components/schemas/StatusEnum'\n          description: 'For more than one parameter, it needs to be indexed. Ex: statuses[0]=ACTIVE&statuses[1]=DRAFT'\n          style: form\n          in: query\n          name: statuses\n        - schema:\n            type: number\n          in: query\n          name: maxResults\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: array\n                items:\n                  $ref: '#/components/schemas/Subscription'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          description: Not Found\n      tags:\n        - Subscription\n  /integration/product:\n    get:\n      summary: Get Product Integration Record from NetSuite\n      operationId: get-integration-product\n      description: |-\n        Retrieve Product Integration Record for Product family (e.g. DNN) and Product Variant (e.g. SA-CUS) in JWT token\n\n        Only allowed with Admin JWT token (i.e. with padm=true flag)\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: array\n                items:\n                  $ref: '#/components/schemas/ProductIntegration'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          description: Not Found\n      tags:\n        - Integration internal\n      security:\n        - PrivilegedToken: []\n  /integration/reportUsage:\n    post:\n      summary: Report Usage/consumption for Subscription's usage type items.\n      operationId: post-integration-report-usage\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: array\n              description: ''\n              items:\n                type: object\n                description: ''\n                properties:\n                  subscriptionId:\n                    type: number\n                    description: Subscription ID to report usage against.\n                  itemCode:\n                    type: string\n                    description: Code of item with type usage. If subscription has more than one item with such code lineNumber must be specified\n                  quantity:\n                    type: number\n                    description: Decimal usage quantity\n                  lineNumber:\n                    type: integer\n                    description: Used if more than one item with same code in subscription. Ignored otherwise\n                  usageDate:\n                    type: string\n                    format: date\n                    description: Date of usage. Subscription must be active on this date\n                required:\n                  - subscriptionId\n                  - itemCode\n                  - quantity\n                  - usageDate\n            x-examples:\n              example-1:\n                value:\n                  - subscriptionId: string\n                    unit: string\n                    quantity: 0\n                    itemId: string\n        description: 'List of usages to report. It can be for same or for different subscriptions/items/dates. '\n      responses:\n        '200':\n          $ref: '#/components/responses/PartialResponse'\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n      description: |-\n        Report consumption for usage based items which should be paid in arrears based on real usage. \n        It is assumed that product manages online numbers and use this method scheduled with batch of items across many customers.\n        Method may return with partially success response, failed records will be reported in errors array.\n      tags:\n        - Report Usage\n      security:\n        - PrivilegedToken: []\n    parameters: []\n  /integration/searchCustomer:\n    post:\n      summary: 'Integration: Search customer in NetSuite'\n      operationId: post-customer-search\n      description: |-\n        Retrieve customers based upon criteria specified in the request body. \n\n        Only allowed with padm=true (Admin) in JWT token\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              properties:\n                firstName:\n                  type: string\n                  maxLength: 32\n                lastName:\n                  type: string\n                  maxLength: 32\n                email:\n                  type: string\n                  format: email\n                companyName:\n                  type: string\n                contactEmail:\n                  type: string\n                  format: email\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: array\n                items:\n                  $ref: '#/components/schemas/Customer'\n        '401':\n          $ref: '#/components/responses/Error'\n        '404':\n          description: Not Found\n      tags:\n        - Integration internal\n      security:\n        - PrivilegedToken: []\n  /integration/netsuiteRelay:\n    post:\n      summary: 'Integration: Passes any request to the NetSuite instance'\n      operationId: post-netsuite-relay\n      description: |-\n        Make a POST request to the NetSuite URL with the body provided.\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              properties:\n                targetNSRequest:\n                  type: string\n                  enum:\n                    - generate_quote\n                    - renewal_order\n                payload:\n                  type: object\n              required:\n                - targetNSRequest\n                - payload\n            example:\n              targetNSRequest: 'generate_quote'\n              payload:\n                op: 'quote.create'\n                productFamilyCode: 'GEN'\n                productVariantCode: 'OP-SUB'\n                customerId: '2861'\n                subscriptionId: 441817\n                content: null\n      responses:\n        '200':\n          description: Success. The response contains the data returned by  NetSuite.\n          content:\n            application/json:\n              schema:\n                type: object\n        '401':\n          description: Security token is incorrect\n          content:\n            application/json:\n              schema:\n                type: object\n                properties:\n                  message:\n                    type: string\n      tags:\n        - Integration internal\n  /subscription/{subscriptionId}/renewal:\n    get:\n      summary: Get the plan and items for renewal.\n      operationId: get-subscription-renewal-info\n      description: Retrieve the code, items and quantity of the latest active subscription plan based on the given input parameters.\n      parameters:\n        - name: subscriptionId\n          in: path\n          required: true\n          schema:\n            type: integer\n        - name: productTier\n          in: query\n          required: true\n          schema:\n            $ref: '#/components/schemas/ProductTierEnum'\n        - name: supportLevel\n          in: query\n          required: true\n          schema:\n            $ref: '#/components/schemas/SupportLevelEnum'\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: object\n                properties:\n                  plan:\n                    type: object\n                    description: the plan\n                    properties:\n                      code:\n                        type: string\n                      description:\n                        type: string\n                      name:\n                        type: string\n                  items:\n                    type: array\n                    items:\n                      type: object\n                      description: the item\n                      properties:\n                        code:\n                          type: string\n                        quantity:\n                          type: number\n                          description: The quantity to be renewed. If the product has a minimnum quantity and current quantity is less than that, the minimum quantity will be returned.\n                        originalQuantity:\n                          type: integer\n                          description: The original quantity before renewal.\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n        '500':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Subscription\n  '/subscription/{subscriptionId}':\n    parameters:\n      - schema:\n          type: string\n        name: subscriptionId\n        in: path\n        required: true\n    get:\n      summary: Get Subscription against a subscription ID\n      operationId: get-subscription-subscriptionId\n      description: Retrieve a subscription against the subscription ID. A validation check for customer id present in JWT Token will be performed to prevent customers from fetching subscriptions of other customers.\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Subscription'\n        '401':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Subscription\n    put:\n      summary: Update an Active or Draft Renewal Subscription.\n      operationId: put-subscription-subscriptionId\n      description: |-\n        Make updates to an Active Subscription or a Draft Renewal Subscription against the Subscription ID provided.\n\n        For Draft Renewal Subscription - Update the existing Draft Subscription if it's just a qauntity change or in case of Subscription Plan change, delete the old draft and generate a new Draft Subscription (returns a new Subscription Id). Keep it in Draft Status until the Quote is accepted.\n\n        For Active Term Subscription Upgrades - Generates a New Draft Subscription with requested changes (returns a new draft Subscription Id). Draft Subscription Start, End Dates and Initial Term will be same as original subscription. The new Draft Subscription with changes is linked to original subscription through a naming convention containing the Original Subscription ID.\n        Customer will retain his current price discounts percentage in case of upgrades. \n\n        For Active Term Subscription Downgrades - Downgrades to Active Term Subscriptions are not allowed.\n\n        For Active Evergreen Subscription - The upgrades to Quantity, Edition or Success Level are applicable immediately, and the downgrades will be applied on the next billing cycle. Evergreen subscriptions do not need to go through quote acceptace process to be activate or updated.\n\n        For Trial Subscription - Trial Subscription Upgrade to the paid subscription follows the same process of active subscription update. If the input of this API is Trial Subscription ID, a draft subscription will be created with required changes.\n      requestBody:\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/UpdateSubscriptionConfiguration'\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Subscription'\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '404':\n          description: Not Found\n      tags:\n        - Subscription\n    patch:\n      summary: Update subscription status e.g. Activate a Draft Subscription\n      operationId: patch-subscription-subscriptionId\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Subscription'\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n      description: |-\n        Activate the subscription against the subscription ID provided in API input.\n\n        If Subscription is an Evergreen Subscription - Then activate the subscription skipping the Quote Acceptance check. \n\n        If Subscription is a Term Subscription - Then activate after verifing if the Quote is accepted, else return error.\n\n        If it's an upgrade scenario, then Activation will also deactivate the old Subscription after activating the upgraded subscription.\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              properties:\n                status:\n                  type: string\n              required:\n                - status\n            examples:\n              example-1:\n                value:\n                  status: ACTIVE\n      tags:\n        - Subscription\n  /customer:\n    get:\n      summary: Get Customer details\n      operationId: get-customer\n      description: Retrieve customer details for customer ID present in JWT Token or specified in input parameter in case of Admin JWT Token.\n      parameters:\n        - schema:\n            type: string\n          in: query\n          name: customerId\n          description: Required if cid is not set in JWT Token.\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Customer'\n        '401':\n          $ref: '#/components/responses/Error'\n        '404':\n          description: Not Found\n      tags:\n        - Customer\n    put:\n      summary: Update Customer details\n      operationId: put-customer\n      description: Update the customer information in NetSuite with the information specified in the request body\n      requestBody:\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/Customer'\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: string\n              example: customerId\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          description: Not Found\n      tags:\n        - Customer\n    patch:\n      summary: Partial update of a customer\n      operationId: patch-customer\n      description: |-\n        Partial update of the customer information in NetSuite based on the request body.\n        - An undefined property will be ignored.\n        - A property set to null will be emptied.\n        - A customer can update its own record.\n        - A customer can update only the shipping address of a related end-user, based on its draft subscriptions.\n      requestBody:\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/Customer'\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: string\n              example: customerId\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          description: Not Found\n      tags:\n        - Customer\n    post:\n      summary: Create a new customer in NetSuite\n      operationId: post-customer\n      description: |-\n        Create a new customer in NetSuite with the information provided in the request body.\n\n        Only allowed with padm=true in JWT token\n      requestBody:\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/Customer'\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: string\n              example: customerId\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Customer\n      security:\n        - PrivilegedToken: []\n  /customer/statement:\n    get:\n      summary: Retrieve customer statement\n      operationId: get-customer-statement\n      description: Retrieve the statement for the customer ID present in JWT Token or specified in input parameter in case of Admin JWT Token.\n      parameters:\n        - schema:\n            type: string\n          in: query\n          name: customerId\n          description: Required if cid is not set in JWT Token.\n        - schema:\n            type: string\n          in: query\n          name: startDate\n          description: Optional. The start date of the statement period with format 01-Jan-2021.\n          required: false\n      responses:\n        '200':\n          description: Customer Statement in base64.\n          content:\n            application/pdf:\n              schema:\n                type: string\n                format: byte\n                description: base64-encoded PDF file\n              example: base64 string\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Customer\n  /customer/latestSignedQuote:\n    get:\n      summary: Retrieve customer latest signed quote\n      operationId: get-customer-latest-signed-quote\n      description: Retrieve the latest signed quote for the customer ID present in JWT Token or specified in input parameter in case of Admin JWT Token.\n      parameters:\n        - schema:\n            type: string\n          in: query\n          name: customerId\n          description: Required if cid is not set in JWT Token.\n        - schema:\n            type: string\n          in: query\n          name: endUserId\n          description: Optional. The end user id in case of a reseller to get the latest signed quote for a specific end user.\n          required: false\n      responses:\n        '200':\n          description: Latest signed quote in base64.\n          content:\n            application/pdf:\n              schema:\n                type: string\n                format: byte\n                description: base64-encoded PDF file\n              example: base64 string\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Customer\n  /subscriptionPlans:\n    get:\n      summary: List available subscription plans\n      operationId: get-subscriptionPlan\n      description: Retrieve Subscription Plans for a product family (e.g. DNN) and product variant (SA-CUS) present in JWT token.\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: array\n                items:\n                  $ref: '#/components/schemas/SubscriptionPlan'\n        '401':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Product catalog\n  /subscriptionPlans/latestCode:\n    get:\n      summary: Get the latest subscription plan code\n      operationId: get-subscriptionPlans-latestCode\n      description: Retrieve the code of the latest active subscription plan based on the given input parameters.\n      parameters:\n        - name: productTier\n          in: query\n          required: true\n          schema:\n            $ref: '#/components/schemas/ProductTierEnum'\n        - name: supportLevel\n          in: query\n          required: true\n          schema:\n            $ref: '#/components/schemas/SupportLevelEnum'\n        - name: isSupport\n          in: query\n          required: true\n          schema:\n            type: boolean\n      responses:\n        '200':\n          description: OK\n          content:\n            text/plain:\n              schema:\n                type: string                \n                description: The subscription plan code.\n                example: DNN CustomerCloud EVOQ, STANDARD EDITION, GOLD SUCCESS-002\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n        '500':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Product catalog\n  /products:\n    get:\n      summary: Get list of products and variants\n      operationId: get-product\n      description: List available products based on Product Family Code and Product Variant in JWT Token\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: array\n                items:\n                  $ref: '#/components/schemas/ProductCoordinates'\n        '401':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Product catalog\n  /invoices:\n    get:\n      summary: List customer invoices\n      operationId: get-invoice\n      description: Retrieve customer invoices from NetSuite filtered by input parameters. Invoices returned also contain the Stripe Invoice Payment Link along with other invoice details.\n      parameters:\n        - schema:\n            type: string\n          in: query\n          name: customerId\n          description: Required for non-customer token\n        - schema:\n            type: string\n          in: query\n          name: subscriptionId\n        - schema:\n            type: string\n          in: query\n          name: startDate\n        - schema:\n            type: string\n          in: query\n          name: endDate\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: array\n                items:\n                  $ref: '#/components/schemas/InvoiceInfo'\n        '401':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Invoices\n  /subscription/preview:\n    post:\n      summary: Calculate subscription pricing for a new subscription purchase.\n      operationId: post-subscription-preview\n      description: 'Calculate subscription prices a customer will be charged for selected Product Edition, Support Plan and Add-Ons with intended quantities.'\n      requestBody:\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/BaseSubscriptionConfiguration'\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Preview'\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Subscription\n  '/subscription/preview/{subscriptionId}':\n    parameters:\n      - schema:\n          type: string\n        name: subscriptionId\n        description: 'Id of an active subscription in case of a upgrade/downgrade, or Id of a Draft Renewal Subscription when calculating prices for a subscription renewal.'\n        in: path\n        required: true\n    post:\n      summary: Calculate subscription pricing for active subscription update or subscription renewal.\n      operationId: post-subscription-preview-susbscriptionId\n      description: 'Calculate final price after applying discounts (if applicable) for Subscription Upgrades, Downgrades or Renewals.'\n      requestBody:\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/ExtendedBaseSubscriptionConfiguration'\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ExtendedPreview'\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Subscription\n  /subscription:\n    post:\n      summary: Create a new Subscription\n      operationId: post-subscription\n      description: |-\n        Create a new subscription in NetSuite with the given configuration in request body. New subscriptions will always be created in Draft status and will be activated as follows:\n\n        If the created subscription is a Term Subscription, then the subscription has to go through Quote Generation and Acceptance process before activation.\n\n        If the created subscription is an Evergreen subscription, then it can directly be activated skipping the Quote flow by calling the PATCH /Subscription API.\n      parameters:\n        - schema:\n            type: string\n          in: query\n          name: customerId\n          description: \"Required for non-customer (Admin) token, i.e. Admin creating Subscription on Customer's behalf\"\n      requestBody:\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/CreateSubscriptionConfiguration'\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Subscription'\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Subscription\n  /subscription/startTrial:\n    post:\n      summary: Start Trial Subscription\n      operationId: post-subscription-startTrial\n      description: |-\n        Start trial subscription based on Trial Subscription Config present in Production Integration record. Trial config specifies the Subscription Plan, Items, Quantities and trial duration in number of days to be used in trial subscription.\n\n        A customer is not eligible for a trial subscription if he already has any trial or paid subscription against his customer account in NetSuite.\n      parameters:\n        - schema:\n            type: string\n          in: query\n          name: customerId\n          description: Required for non-customer token\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Subscription'\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Subscription  \n  '/subscription/{subscriptionId}/contractualDocuments':\n    post:\n      summary: Create a contractual document\n      operationId: post-subscription-contractualDocuments\n      description: |-\n        Create a contractual document by uploading a PDF file and attaching it to the existing contractual documents record.\n      parameters:\n        - name: subscriptionId\n          in: path\n          description: The identifier of the target subscription.\n          required: true\n          schema:\n            type: integer\n        - name: customerId\n          in: query\n          description: The customer ID (entity ID). Required only for non-customer (admin) token.\n          schema:\n            type: string\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              properties:\n                type:\n                  $ref: '#/components/schemas/ContractualDocumentTypeEnum'\n                filename:\n                  type: string\n                  description: The filename, including the extension. Only PDF files are supported.\n                contents:\n                  type: string\n                  description: The base64-encoded representation of the file contents.\n              required:\n                - type\n                - filename\n                - contents\n              example:\n                type: 'purchase-order'\n                filename: 'sample.pdf'\n                contents: 'JVBERi0xLjMNCiXi48/T...MjcxNA0KJSVFT0YNCg=='\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: object\n                properties:\n                  contractualDocumentsId:\n                    type: integer\n                    description: The identifier of the contractual documents record related to the target subscription.\n                  fileId:\n                    type: integer\n                    description: The identifier of the uploaded file.\n                required:\n                  - contractualDocumentsId\n                  - fileId\n                example:\n                  contractualDocumentsId: 145482\n                  fileId: 16273973\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n        '500':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Subscription\n  '/subscription/{subscriptionId}/renewalIntent':\n    post:\n      summary: Record latest renewal intent.\n      operationId: post-subscription-renewalIntent\n      description: |-\n        Records the date/time of a renewal intent on a certain subscription (opportunity).\n      parameters:\n        - name: subscriptionId\n          in: path\n          description: The identifier of the target subscription.\n          required: true\n          schema:\n            type: integer\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: object\n                properties:\n                  subscriptionId:\n                    type: integer\n                    description: The identifier of the target subscription.\n                  lastActivity:\n                    type: string\n                    description: The date/time recorded as the last renewal activity (ISO format).\n                required:\n                  - subscriptionId\n                  - lastActivity\n                example:\n                  subscriptionId: 1160600\n                  lastActivity: \"2024-02-08T16:40:33.708Z\"\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n        '500':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Subscription\n  '/subscription/{subscriptionId}/updateRenewalPrimaryContact':\n    patch:\n      summary: Update renewal primary contact\n      operationId: post-subscription-updateRenewalPrimaryContact\n      parameters:\n        - name: subscriptionId\n          in: path\n          description: The identifier of the target subscription.\n          required: true\n          schema:\n            type: integer\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              properties:\n                primaryContact:\n                  $ref: '#/components/schemas/Contact'\n      responses:\n        '200':\n          description: Successful response\n        '400':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Subscription\n  '/subscription/{subscriptionId}/getRenewalPrimaryContact':\n    parameters:\n      - name: subscriptionId\n        in: path\n        required: true\n        schema:\n          type: integer\n    get:\n      summary: Get renewal primary contact\n      operationId: get-subscription-getRenewalPrimaryContact\n      description: |-\n        Get the renewal primary contact for the given subscription.\n      responses:\n        '200':\n          description: Successful response\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Contact'\n        '400':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Subscription\n  '/invoice/{number}/download':\n    parameters:\n      - schema:\n          type: string\n        name: number\n        in: path\n        required: true\n        description: Invoice Number taken from the List Invoices API response.\n    get:\n      summary: Download Invoice document\n      operationId: get-invoice-download\n      description: Download Invoice PDF document in base64 format for the given invoice Id in API Input.\n      responses:\n        '200':\n          description: OK\n          content:\n            application/pdf:\n              schema:\n                type: string\n                format: base64\n              example: base64 string\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Invoices\n  /voiceflow/updateVariables:\n    post:\n      summary: Update Voiceflow variables\n      operationId: post-voiceflow-updateVariables\n      description: Update variables for a specific user in Voiceflow\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              required:\n                - userID\n                - variables\n              properties:\n                userID:\n                  type: string\n                  description: The ID of the user in Voiceflow\n                variables:\n                  type: object\n                  description: The variables to update\n                  additionalProperties: true\n      responses:\n        '200':\n          description: Variables updated successfully\n          content:\n            application/json:\n              schema:\n                type: object\n                properties:\n                  message:\n                    type: string\n        '400':\n          description: Bad request\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '500':\n          description: Internal server error\n          $ref: '#/components/responses/Error'\n      tags:\n        - Voiceflow\n      security:\n        - Token: []\n  /quote:\n    post:\n      summary: Generate a NetSuite Quote\n      operationId: post-quote\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: object\n                properties:\n                  id:\n                    type: number\n                    description: Id of quote created\n                  quoteType:\n                    type: string\n                    enum: ['FullTCs', 'NoTCs', 'Reseller', 'Other']\n                required:\n                  - id\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n      description: 'Create a Quote in NetSuite against a draft term subscription. The Draft subscription can be a new subscription, an upgrade of an active paid or trial subscription or a draft renewal subscription.'\n      tags:\n        - Quote\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              properties:\n                subscriptionId:\n                  type: integer\n                orderType:\n                  type: string\n                  pattern: '^([Rr][Ee][Nn][Ee][Ww][Aa][Ll]|[Qq][Uu][Oo][Tt][Ee])$'\n                recipients:\n                  type: array\n                  items:\n                    type: object\n                    properties:\n                      email:\n                        type: string\n                      role:\n                        type: string\n                        pattern: '^([Cc][Cc]|[Ss][Ii][Gg][Nn][Ee][Rr])$'\n                    required:\n                      - email\n                      - role\n                expiry:\n                  type: string\n                  pattern: '^(\\d{2}-\\w{3}-\\d{4})$'\n                quoteLineStartDates:\n                  type: array\n                  items:\n                    type: object\n                    properties:\n                      line:\n                        type: string\n                      startDate:\n                        type: string\n                    required:\n                      - line\n                      - startDate\n                quoteLineEndDates:\n                  type: array\n                  items:\n                    type: object\n                    properties:\n                      line:\n                        type: string\n                      endDate:\n                        type: string\n                    required:\n                      - line\n                      - endDate\n                salesRep:\n                  type: number\n                lineItemsHeaderText:\n                  type: string\n                lineItemsFooterText:\n                  type: string\n                terms:\n                  type: string\n              required:\n                - subscriptionId\n  /quote/createForSelfServe:\n    post:\n      summary: Create a NetSuite Quote for Self-Serve\n      operationId: post-quote-create-for-self-serve\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: object\n                properties:\n                  id:\n                    type: number\n                    description: Id of quote created\n                required:\n                  - id\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n      description: 'Create a quote soft-linked to a renewal subscription in NetSuite.'\n      tags:\n        - Quote\n      requestBody:\n        content:\n          application/json:\n            schema:\n              allOf:\n                - type: object\n                  properties:\n                    subscriptionId:\n                      type: integer\n                    ccRecipients:\n                      type: array\n                      description: A list of recipients. If defined, this array must contain one and only one signer. If there is no signer, this list will be ignored. If there are more than one signer, an error will be thrown.\n                      items:\n                        type: object\n                        properties:\n                          email:\n                            type: string\n                            description: The email address of the recipient, or an email list separated by comma or semicolon characters.\n                        required:\n                          - email\n                    signer:\n                      $ref: '#/components/schemas/Contact'\n                - $ref: '#/components/schemas/BaseSubscriptionConfiguration'\n              required:\n                - subscriptionId\n                - planCode\n                - items\n                - frequency\n                - duration\n              example:\n                subscriptionId: 10\n                ccRecipients:\n                  - email: first-cc@customer.com\n                  - email: second-cc@customer.com\n                planCode: Kayako TNK GROWTH PLATINUM\n                items:\n                  - code: Kay-SA-TNK-STA\n                    quantity: 25\n                  - code: Kay-SA-COL-STA\n                    quantity: 2\n                frequency: MONTHLY\n                duration: 12\n                signer:\n                  name:\n                    title: Mr\n                    firstName: John\n                    lastName: Doe\n                  email: john.doe@example.com\n                  phone: 1234567890\n  '/quote/{quoteId}/download':\n    parameters:\n      - schema:\n          type: integer\n        name: quoteId\n        in: path\n        required: true\n    get:\n      summary: Download quote PDF\n      tags:\n        - Quote\n      responses:\n        '200':\n          description: OK\n          headers: {}\n          content:\n            application/pdf:\n              schema:\n                type: string\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n      operationId: get-quote-quoteId-download\n      description: |-\n        Download quote PDF in base64 format against the quote id provided in API input.\n\n        The Quote PDF will also contain the Terms and Conditions PDF appended with Quote document. The Terms and Conditions PDF document is taken from Product Integration Record.\n  '/quote/{quoteId}/accept':\n    parameters:\n      - schema:\n          type: integer\n        name: quoteId\n        in: path\n        required: true\n    post:\n      summary: 'Accept quote, save acceptance parameters and email Quote for eSignatures.'\n      operationId: post-quote-quoteId-accept\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: object\n                properties:\n                  id:\n                    type: integer\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n      description: |-\n        Accept quote and record the customer acceptance details (e.g. Acceptor's name, title, email, ccEmail, time of acceptance and IP Address) in a contractual document object in NetSuite. The contractual document also contains the link to accepted quote and conractual document is linked to the subscription through the Contractual Document Field.\n\n        Once the Quote is accepted, an Adobe eSign agreement is also created in NetSuite against the accepted Quote and emailed to Acceptor for eSignatures, and also cc'ed to ccEmail if specified.\n\n        Once the Quote is accepted through API, the related Term Subscription can be activated. The eSignatures through email is an asynchronous operation and does not prevent the subscription from activation.\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              properties:\n                acceptor:\n                  type: object\n                  required:\n                    - name\n                    - jobTitle\n                    - email\n                    - phone\n                  properties:\n                    name:\n                      type: string\n                      minLength: 1\n                      pattern: ^\\S.+\n                    jobTitle:\n                      type: string\n                      pattern: ^\\S.+\n                      minLength: 1\n                    email:\n                      type: string\n                      format: email\n                    phone:\n                      type: string\n                      pattern: ^\\S.+\n                      minLength: 1\n                ccEmail:\n                  type: string\n                  format: email\n                  nullable: true\n              required:\n                - acceptor\n            examples:\n              example-1:\n                value:\n                  acceptor:\n                    name: Tyler\n                    jobTitle: COO\n                    email: tyler@paperstreetsoap.com\n                    phone: (288) 555-0153\n                  ccEmail: thenarrator2@paperstreetsoap.com\n      tags:\n        - Quote\n  '/quote/{quoteId}/poDocument':\n    post:\n      summary: Attach PO Document to Quote\n      operationId: post-quotes-quoteId-poDocument\n      description: Attach a PO document to the quote\n      parameters:\n        - name: quoteId\n          in: path\n          description: The unique identifier of the quote to which the PO document is to be attached.\n          required: true\n          schema:\n            type: string\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              properties:\n                poDocument:\n                  type: string\n                  description: The base64-encoded representation of the file contents. Only PDF files are supported.\n                poNumber:\n                  type: string\n                  description: The purchase order number.\n              required:\n                - poDocument\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: object\n                properties:\n                  poNetsuiteFileId:\n                    type: integer\n                    description: The identifier of the PO document in NetSuite.\n        '400':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n        '500':\n          $ref: '#/components/responses/Error'\n      tags:\n        - Quote\n  /invoice:\n    parameters: []\n    post:\n      summary: Generate a new invoice for a billing account.\n      operationId: post-invoice\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/InvoiceInfo'\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n      description: |-\n        Generate an invoice against a billing account of a customer. This API is intended to be used for new customers who made a first time purchase and have no previous active subscription available. This API would generate an Invoice for the new purchase made and present the customer with a Stripe Invoice Payment link to make the payment.\n\n        The Subscription ID in input would correctly determine the billing account to be used and also specifies the subscription he has just purchased which needs to be invoiced.\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              properties:\n                subscriptionId:\n                  type: integer\n              required:\n                - subscriptionId\n      tags:\n        - Invoices\n  /ui/customer/interests/:\n    post:\n      summary: Enrolls the customer in the interests of specific prime products.\n      description: |\n        The customer will be enrolled in the interests of the prime products specified in the request body.\n        \n        This request works only for a customer context, as the email address is retrieved from the JWT token.\n      tags:\n        - UI customer\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              properties:\n                subscriptionId:\n                  type: integer\n                  description: The active subscription currently undergoing the renewal process (i.e. the parent subscription).\n                productCodes:\n                  type: array\n                  description: A list of prime products.\n                  items:\n                    type: string\n                    description: A prime product code, with case-insensitive matching.\n              required:\n                - subscriptionId\n                - productCodes\n              example:\n                subscriptionId: 1196564\n                productCodes:\n                  - Cloudfix\n                  - Crossover\n      responses:\n        '204':\n          description: Successful response. No content.\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n        '500':\n          $ref: '#/components/responses/Error'\n  /ui/customer/support:\n    post:\n      summary: Submits a customer support request.\n      description: |\n        The customer support request will be submitted to the customer support team.\n\n        This request works only for a customer context, as the email address is retrieved from the JWT token.\n      tags:\n        - UI customer\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              properties:\n                subscriptionId:\n                  type: integer\n                  description: The identifier of the subscription to be renewed.\n                message:\n                  type: string\n                  description: The customer's request message.\n                firstName:\n                  type: string\n                  description: The customer's first name.\n                lastName:\n                  type: string\n                  description: The customer's last name.\n                phone:\n                  type: string\n                  description: The customer's phone number.\n              required:\n                - subscriptionId\n                - message\n              example:\n                subscriptionId: 123456\n                message: \"I need assistance with my subscription.\"\n                firstName: \"John\"\n                lastName: \"Doe\"\n                phone: \"123-456-7890\"\n      responses:\n        '204':\n          description: Successful response. No content.\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n        '500':\n          $ref: '#/components/responses/Error'\n  /ui/storage:\n    get:\n      summary: Get the content stored for a given subscription in the user context.\n      tags:\n        - UI storage\n      parameters:\n        - name: subscriptionId\n          in: query\n          required: true\n          schema:\n            type: string\n            description: The identifier of the subscription.\n      responses:\n        '200':\n          description: Successful response.\n          content:\n            application/json:\n              schema:\n                type: object\n                description: The JSON content stored. The default value is null.\n                additionalProperties: {}\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '500':\n          $ref: '#/components/responses/Error'\n    put:\n      summary: Update the content stored for a given subscription in the user context.\n      tags:\n        - UI storage\n      parameters:\n        - name: subscriptionId\n          in: query\n          required: true\n          schema:\n            type: string\n            description: The identifier of the subscription.\n      requestBody:\n        required: true\n        content:\n          application/json:\n            schema:\n              type: object\n              description: The JSON content to store.\n              additionalProperties: {}\n      responses:\n        '204':\n          description: Content updated successfully.\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '500':\n          $ref: '#/components/responses/Error'\n  '/ui/subscription/{subscriptionId}/agreementStatus':\n    parameters:\n      - schema:\n          type: integer\n        name: subscriptionId\n        in: path\n        required: true\n    get:\n      summary: Get the most advanced agreement status of Self-Serve quotes for the given subscription.\n      tags:\n        - UI subscription\n      responses:\n        '200':\n          description: Successful response.\n          content:\n            text/plain:\n              schema:\n                $ref: '#/components/schemas/AgreementStatusResponseEnum'\n        '400':\n          $ref: '#/components/responses/Error'\n        '401':\n          $ref: '#/components/responses/Error'\n        '403':\n          $ref: '#/components/responses/Error'\n        '404':\n          $ref: '#/components/responses/Error'\n        '500':\n          $ref: '#/components/responses/Error'\ncomponents:\n  schemas:\n    CustomerInfo:\n      type: object\n      description: Short customer info to match. If customer is company - companyName will be not empty\n      example:\n        id: '4651565415'\n        firstName: John\n        lastName: Smith\n        email: john.smith@example.com\n        companyName: Smith tools\n        taxIdentificationNumber: ABCDF1234J\n        address:\n          line1: 536 Paper street\n          line2: 2nd floor\n          city: Bradford\n          state: DE\n          country: US\n          zip: '19808'\n          phone: 111-111-111\n        shippingAddress:\n          line1: 17 Sheet street\n          line2: 3rd floor\n          city: Texas City\n          state: TX\n          country: US\n          zip: '12345'\n          phone: 222-222-222\n        primaryContact:\n          name:\n            title: Mr\n            firstName: Tyler\n            middleName: E\n            lastName: Durden\n          email: tyler@paperstreetsoap.com\n          phone: (288) 555-0153\n          billingAddress:\n            line1: 536 Paper street\n            line2: 2nd floor\n            city: Bradford\n            state: DE\n            country: US\n            zip: '19808'\n            phone: 111-111-111\n      x-examples:\n        example-1:\n          id: '4651565415'\n          firstName: John\n          lastName: Smith\n          email: john.smith@example.com\n          companyName: Smith tools\n          taxIdentificationNumber: ABCDF1234K\n          address:\n            line1: 536 Paper street\n            line2: 2nd floor\n            city: Bradford\n            state: DE\n            country: US\n            zip: '19808'\n            phone: 111-111-111\n          shippingAddress:\n            line1: 17 Sheet street\n            line2: 3rd floor\n            city: Texas City\n            state: TX\n            country: US\n            zip: '12345'\n            phone: 222-222-222\n          primaryContact:\n            name:\n              title: Mr\n              firstName: Tyler\n              middleName: E\n              lastName: Durden\n            email: tyler@paperstreetsoap.com\n            phone: (288) 555-0153\n            billingAddress:\n              line1: 536 Paper street\n              line2: 2nd floor\n              city: Bradford\n              state: DE\n              country: US\n              zip: '19808'\n              phone: 111-111-111\n      properties:\n        id:\n          type: string\n        firstName:\n          type: string\n          maxLength: 32\n        lastName:\n          type: string\n          maxLength: 32\n        email:\n          type: string\n          format: email\n        phone:\n          type: string\n        companyName:\n          type: string\n        taxIdentificationNumber:\n          type: string\n          description: The tax identification number of the customer.\n          example: ABCDF1234J\n          nullable: true\n        address:\n          description: The billing address, and if not defined separately, the shipping address.\n          allOf:\n            - $ref: '#/components/schemas/Address'\n        shippingAddress:\n          description: The shipping address, if different from the billing address.\n          allOf:\n            - $ref: '#/components/schemas/Address'\n        primaryContact:\n          $ref: '#/components/schemas/Contact'\n    Subscription:\n      type: object\n      example:\n        id: 487524\n        status: DRAFT\n        currency: USD\n        customer:\n          id: '4651565415'\n          firstName: John\n          lastName: Smith\n          email: john.smith@example.com\n          phone: '1234567'\n          companyName: Smith tools\n          taxIdentificationNumber: ABCDF1234J\n          address:\n            line1: 536 Paper street\n            line2: 2nd floor\n            city: Bradford\n            state: DE\n            country: US\n            zip: '19808'\n            phone: 111-111-111\n          shippingAddress:\n            line1: 17 Sheet street\n            line2: 3rd floor\n            city: Texas City\n            state: TX\n            country: US\n            zip: '12345'\n            phone: 222-222-222\n        endUser:\n          id: '4651565415'\n          firstName: John\n          lastName: Smith\n          email: john.smith@example.com\n          phone: '1234567'\n          companyName: Smith tools\n          taxIdentificationNumber: ABCDF1234L\n          address:\n            line1: 536 Paper street\n            line2: 2nd floor\n            city: Bradford\n            state: DE\n            country: US\n            zip: '19808'\n            phone: 111-111-111\n          shippingAddress:\n            line1: 17 Sheet street\n            line2: 3rd floor\n            city: Texas City\n            state: TX\n            country: US\n            zip: '12345'\n            phone: 222-222-222\n        serialOrLicenseNumber: 112233\n        plan:\n          id: 85156\n          code: Kay-SA-TNK-STA-PLA\n          description: Kayako TNK Growth, Platinum Success\n          title: Kayako TNK GROWTH PLATINUM\n          productTier: Standard\n          productTierTitle: Standard\n          supportLevel: Platinum\n          revenueType: SaaS\n          isTrial: false\n        items:\n          - id: 82865\n            code: Kay-SA-TNK-STA\n            title: Kayako TNK Standard\n            type: Recurring\n            typeId: 2\n            desc: description\n            minQuantity: 1\n            maxQuantity: 10000\n            required: true\n            prices:\n              - type: Tiered\n                frequency: ANNUALLY\n                pricebookid: 10611\n                ranges:\n                  - priceplanid: 4889293\n                    type: Rate\n                    fromQuantity: 0\n                    price: 10\n                  - priceplanid: 4889293\n                    type: Rate\n                    fromQuantity: 1000\n                    price: 9\n              - type: Tiered\n                frequency: MONTHLY\n                ranges:\n                  - fromQuantity: 0\n                    price: 11\n                  - fromQuantity: 1000\n                    price: 10\n            amount: 50\n            totalIntervalValue: 40\n            productTier: Standard\n            revenueType: SaaS\n        includedItems:\n          - id: 82865\n            code: Kay-SA-TNK-STA\n            quantity: 5\n        term:\n          start: 1-Nov-2021\n          end: 31-Oct-2022\n          frequency: ANNUALLY\n          nextBillCycleDate: 1-Dec-2021\n        autorenewal: false\n        parentSubscription: 545457\n        renewalNumber: 2\n        totalAmount: 50\n        totalIntervalValue: 40\n        operations:\n          ['renew', 'changeEdition', 'changeSuccessPlan', 'changeQuantity', 'changeTerm', 'changeBillingFrequency']\n        quotes:\n          - id: 36891513\n            isSelfServe: true\n            quoteNumber: 123\n            createddate: '2022-01-01 00:00:00'\n            status: Draft\n            productTier: Standard\n            successLevel: Platinum\n            duration: 12\n            averageARR: 100\n            totalIntervalValue: 1000\n            agreements:\n              - id: 204502\n                type: 'Quote'\n                status: 'Draft'\n              - id: 204503\n                type: 'End User Agreement'\n                status: 'Draft'\n          - id: 36891514\n            isSelfServe: false\n            quoteNumber: 1234\n            createddate: '2022-02-01 00:00:00'\n            status: Draft\n            productTier: Standard\n            successLevel: Platinum\n            duration: 12\n            averageARR: 100\n            totalIntervalValue: 1000\n            agreements:\n              - id: 204504\n                type: 'Quote'\n                status: 'Out For Signature'\n          - id: 36891515\n            isSelfServe: false\n            quoteNumber: 1235\n            createddate: '2022-03-01 00:00:00'\n            status: Draft\n            productTier: Standard\n            successLevel: Platinum\n            duration: 12\n            averageARR: 100\n            totalIntervalValue: 1000\n            agreements: []\n        excludeFromSelfServe: false\n        isPrime: false\n        priceReset: false\n        renewalPrimaryContact:\n          $ref: '#/components/schemas/Contact'\n        operationDenialReasons:\n          renew: 'Subscription end date is not close enough'\n      properties:\n        id:\n          type: number\n          readOnly: true\n        status:\n          $ref: '#/components/schemas/StatusEnum'\n        currency:\n          type: string\n          maxLength: 3\n          minLength: 3\n          description: ISO currency code\n        customer:\n          $ref: '#/components/schemas/CustomerInfo'\n        distributor:\n          $ref: '#/components/schemas/CustomerInfo'\n        reseller:\n          $ref: '#/components/schemas/CustomerInfo'\n        enduser:\n          $ref: '#/components/schemas/CustomerInfo'\n        serialOrLicenseNumber:\n          type: string\n        plan:\n          $ref: '#/components/schemas/SubscriptionPlanInfo'\n        items:\n          type: array\n          items:\n            allOf:\n              - $ref: '#/components/schemas/SubscriptionLineItem'\n              - type: object\n                properties:\n                  amount:\n                    type: number\n        includedItems:\n          type: array\n          items:\n            type: object\n            properties:\n              id:\n                type: number\n              code:\n                type: string\n              quantity:\n                type: number\n            required:\n              - code\n        term:\n          type: object\n          required:\n            - start\n            - frequency\n          properties:\n            start:\n              type: string\n            end:\n              type: string\n            frequency:\n              $ref: '#/components/schemas/FrequencyEnum'\n            nextBillCycleDate:\n              type: string\n        autorenewal:\n          type: boolean\n        parentSubscriptionId:\n          type: number\n          description: ID of previous subscription (active or not) if this subscription is renewal\n        renewalNumber:\n          type: number\n          description: Renewal cycle number\n        totalAmount:\n          type: number\n        totalIntervalValue:\n          type: number\n        operations:\n          type: array\n          items:\n            type: string\n            pattern: '^(renew|changeEdition|changeSuccessPlan|changeQuantity|changeTerm|changeBillingFrequency)$'\n        quotes:\n          type: array\n          items:\n            $ref: '#/components/schemas/Quote'\n        excludeFromSelfServe:\n          type: boolean\n        isPrime:\n          type: boolean\n        priceReset:\n          type: boolean\n        renewalPrimaryContact:\n          $ref: '#/components/schemas/Contact'\n        operationDenialReasons:\n          type: object\n          properties:\n            renew:\n              type: string\n              enum:\n                - 'Subscription end date is not close enough'\n                - 'Subscription is excluded from self serve'\n                - 'Subscription is prime'\n                - 'Subscription sold through Reseller or Distributor, end user can’t renew'\n                - 'Subscription has a pending activation'\n                - 'Subscription is of $0'\n                - 'Product is not enabled for Self-Serve'\n                - 'Subscription has no draft renewal'\n                - 'Subscription is not active'\n                - 'The related draft subscription was terminated'\n              description: |\n                Reason for denying the renewal operation. Possible values:\n                - 'Subscription end date is not close enough': The subscription's end date is too far in the future to allow renewal (e.g., there are more than 220 days until the end date).\n                - 'Subscription is excluded from self serve': The subscription has been manually excluded from renewing via the Self-Serve Portal by checking the 'Exclude from Self-Serve' checkbox on the subscription page.\n                - 'Subscription is prime': Prime subscriptions are complementary free licenses when buying a different product. They require special handling and cannot be renewed through the Self-Serve Portal. A Prime subscription is identified by the 'Prime' checkbox on the subscription page.\n                - 'Subscription sold through Reseller or Distributor, end user can't renew': End users cannot renew subscriptions sold through partners. Such a subscription has a different 'End User' attribute than the 'Customer.'\n                - 'Subscription has a pending activation': The active parent subscription already has a child subscription in 'Pending Activation' status. The renewal process is almost finished; the only thing remaining is for the child subscription to go into 'Active' status and for the parent to get into 'Closed' status.\n                - 'Subscription is of $0': Free subscriptions cannot be renewed through the Self-Serve Portal. The $0 results from analyzing the Total Interval Value at the item Lines & Pricing level (not the ARR at the subscription level).\n                - 'Product is not enabled for Self-Serve': The 'Self-Serve' checkbox is not checked in the product's Class record associated with this subscription (via the subscription's Class attribute, not the subscription plan's Class).\n                - 'Subscription has no draft renewal': A related child subscription must exist in Draft status before the renewal process can begin.\n                - 'Subscription is not active': Only active subscriptions can be renewed.\n                - 'The related draft subscription was terminated': The draft child subscription has been terminated (at the items level), preventing renewal.\n          description: \"Detailed reasons for each operation that was denied, keyed by operation type.\"\n      required:\n        - id\n        - status\n        - plan\n        - term\n        - items\n        - includedItems\n        - excludeFromSelfServe\n        - priceReset\n      x-examples:\n        example-1:\n          id: 487524\n          status: ACTIVE\n          currency: USD\n          customer:\n            id: '4651565415'\n            firstName: John\n            lastName: Smith\n            email: john.smith@example.com\n            company: Smith tools\n          enduser:\n            id: '4651565415'\n            firstName: John\n            lastName: Smith\n            email: john.smith@example.com\n            company: Smith tools\n          serialOrLicenseNumber: 112233\n          plan:\n            id: 82902\n            code: Premium Plan\n            description: Premium Plan description\n            title: The Premium Plan\n            productTier: Standard\n            supportLevel: Silver\n            revenueType: SaaS\n            isTrial: false\n          items:\n            - id: 82865\n              code: DNN-SA-CUS-BA\n              title: item title\n              type: Recurring\n              desc: description\n              minQuantity: 1\n              maxQuantity: 10000\n              required: true\n              prices:\n                - type: Tiered\n                  frequency: ANNUALLY\n\n                  ranges:\n                    - fromQuantity: 0\n                      price: 10\n                    - fromQuantity: 1000\n                      price: 9\n                - type: Tiered\n                  frequency: MONTHLY\n                  ranges:\n                    - fromQuantity: 0\n                      price: 11\n                    - fromQuantity: 1000\n                      price: 10\n              amount: 50\n          includedItems:\n            - id: 82865\n              code: DNN-SA-CUS-BA\n              quantity: 5\n          term:\n            start: 1-NOV-2021\n            end: 31-OCT-2022\n            frequency: ANNUALLY\n          autorenewal: false\n          parentSubscription: 545457\n          renewalNumber: 2\n          totalAmount: 50\n          excludeFromSelfServe: false\n          isPrime: false\n          priceReset: false\n      description: |-\n        Subscription view model.\n        Pricing and amounts will hidden if current user is not customer.\n    Quote:\n      description: |-\n        Quote view model.\n      type: object\n      properties:\n        id:\n          type: number\n          readOnly: true\n        isSelfServe:\n          type: boolean\n          readOnly: true\n          description: Whether the quote is a self-serve quote or not.\n        quoteNumber:\n          type: integer\n        createddate:\n          type: string\n          format: date-time\n        status:\n          type: string\n        productTier:\n          type: string\n        successLevel:\n          type: string\n        duration:\n          type: integer\n          description: Term duration in months\n        averageARR:\n          type: number\n        totalIntervalValue:\n          type: number  \n        agreements:\n          type: array\n          items:\n            $ref: '#/components/schemas/Agreement'\n      required:\n        - id\n        - isSelfServe\n        - quoteNumber\n        - createddate\n        - status\n        - duration\n        - averageARR\n        - totalIntervalValue\n    Agreement:\n      description: |-\n        Agreement view model.\n      type: object\n      properties:\n        id:\n          type: number\n          readOnly: true\n        type:\n          $ref: '#/components/schemas/AgreementTypeEnum'\n        status:\n          $ref: '#/components/schemas/AgreementStatusEnum'\n      required:\n        - id\n        - status\n    ProductIntegration:\n      type: object\n      properties:\n        family:\n          $ref: '#/components/schemas/CodeAndTitle'\n        variant:\n          $ref: '#/components/schemas/CodeAndTitle'\n        notification:\n          $ref: '#/components/schemas/UrlAndAuth'\n        secret:\n          type: string\n      example:\n        family:\n          code: SOC\n          title: Sococo\n        variant:\n          code: SA\n          title: SaaS\n        notification:\n          url: 'https://app.sococo.com/sievent'\n          auth:\n            username: eventuser\n            password: eventpassword\n        secret: lrfer2jvf3\n    Event:\n      title: Event\n      type: object\n      description: |-\n        Body structure to be sent to webhook. \n\n        **content** structure depends on **type**. For **type**=\"subscription_X\" it will be SubscriptionInfo\n      x-examples:\n        example-1:\n          type: subscription_created\n          content:\n            id: 487524\n            status: ACTIVE\n            currency: USD\n            customer:\n              id: '4651565415'\n              firstName: John\n              lastName: Smith\n              email: john.smith@example.com\n              company: Smith tools\n            enduser:\n              id: '4651565415'\n              firstName: John\n              lastName: Smith\n              email: john.smith@example.com\n              company: Smith tools\n            plan:\n              id: 82902\n              code: Premium Plan\n              title: The Premium Plan\n              productTier: Standard\n              supportLevel: Silver\n              revenueType: SaaS\n              isTrial: false\n            items:\n              - id: 82865\n                code: DNN-SA-CUS-BA\n                title: item title\n                type: Recurring\n                desc: description\n                minQuantity: 1\n                maxQuantity: 10000\n                required: true\n                prices:\n                  - type: Tiered\n                    frequency: ANNUALLY\n                    ranges:\n                      - fromQuantity: 0\n                        price: 10\n                      - fromQuantity: 1000\n                        price: 9\n                  - type: Tiered\n                    frequency: MONTHLY\n                    ranges:\n                      - fromQuantity: 0\n                        price: 11\n                      - fromQuantity: 1000\n                        price: 10\n                amount: 50\n            includedItems:\n              - id: 82865\n                code: DNN-SA-CUS-BA\n                quantity: 5\n            term:\n              start: 1-NOV-2021\n              end: 31-OCT-2022\n              frequency: ANNUALLY\n            autorenewal: false\n            parentSubscription: 545457\n            renewalNumber: 2\n            totalAmount: 50\n          date: '2019-08-24'\n      properties:\n        type:\n          type: string\n          enum:\n            - subscription_created\n            - subscription_updated\n            - subscription_terminated\n          description: Event type\n        content:\n          $ref: '#/components/schemas/Subscription'\n        date:\n          type: string\n          format: date\n          description: Date when event happened\n      required:\n        - type\n        - content\n        - date\n    SubscriptionItem:\n      title: SubscriptionItem\n      type: object\n      x-examples:\n        example-1:\n          id: string\n          code: string\n          title: string\n          quantity: 2\n          status: ACTIVE\n          type: onetime\n      properties:\n        id:\n          type: number\n        code:\n          type: string\n        title:\n          type: string\n        quantity:\n          type: number\n        status:\n          type: string\n          enum:\n            - ACTIVE\n            - PENDING_ACTIVATION\n            - SUSPENDED\n            - DRAFT\n            - CLOSED\n            - TERMINATED\n            - NOT_INCLUDED\n        type:\n          type: string\n          enum:\n            - onetime\n            - requrring\n            - usage\n      required:\n        - code\n        - quantity\n        - status\n        - type\n    SubscriptionPlanInfo:\n      type: object\n      title: SubscriptionPlanInfo\n      properties:\n        id:\n          type: number\n        code:\n          type: string\n        description:\n          type: string\n          description: Description of the subscription plan\n        title:\n          type: string\n          description: Subscription plan name\n        productTier:\n          $ref: '#/components/schemas/ProductTierEnum'\n        productTierTitle:\n          type: string\n        supportLevel:\n          $ref: '#/components/schemas/SupportLevelEnum'\n        revenueType:\n          type: string\n        isTrial:\n          type: boolean\n      required:\n        - id\n        - code\n    SubscriptionPlan:\n      title: SubscriptionPlan\n      type: object\n      x-examples:\n        example-Sococo-Unlimited:\n          id: '123'\n          code: SOC-SUB-UNLIMITED\n          _ns_displayname: SOC-SUB-UNLIMITED\n          description: Sococo Unlimited\n          title: Sococo Unlimited\n          isTrial: false\n          product:\n            family:\n              code: SOC\n              title: SOC\n            variant:\n              code: SA\n              title: SaaS\n          initialterm:\n            name: Annual - 1 Year\n            unit: MONTHS\n            duration: 12\n            type: STANDARD\n          items:\n            - id: '123'\n              code: SOC-SUBI-USERS\n              title: Users\n              type: required\n              desc: Number of seats\n              maxQuantity: 999999\n              minQuantity: 10\n              prices:\n                - type: tiered\n                  frequency: monthly\n                  ranges:\n                    - fromQuantity: 0\n                      price: 42\n                  currency: USD\n            - id: '123'\n              code: SOC-SUBI-MEDIA-PKG\n              title: Media minutes\n              type: addon\n              desc: 1000 minutes\n              maxQuantity: 999999\n              minQuantity: 0\n              prices:\n                - type: tiered\n                  frequency: monthly\n                  ranges:\n                    - fromQuantity: 0\n                      price: 13\n                  currency: USD\n        example-Sococo-Standard:\n          id: '234'\n          code: SOC-SUB-STD\n          _ns_displayname: SOC-SUB-STD\n          description: Sococo\n          title: Sococo\n          isTrial: false\n          product:\n            family:\n              code: SOC\n              title: SOC\n            variant:\n              code: SA\n              title: SaaS\n          initialterm:\n            name: Annual - 1 Year\n            unit: MONTHS\n            duration: 12\n            type: STANDARD\n          items:\n            - id: '123'\n              code: SOC-SUBI-USERS\n              title: Users\n              type: required\n              desc: Number of seats\n              maxQuantity: 999999\n              minQuantity: 10\n              prices:\n                - type: tiered\n                  frequency: monthly\n                  ranges:\n                    - fromQuantity: 0\n                      price: 68\n                  currency: USD\n            - id: '123'\n              code: SOC-SUBI-MEDIA-PKG\n              title: Media minutes\n              type: addon\n              desc: 1000 minutes\n              maxQuantity: 999999\n              minQuantity: 0\n              prices:\n                - type: tiered\n                  frequency: monthly\n                  ranges:\n                    - fromQuantity: 0\n                      price: 13\n                  currency: USD\n          productTier: Standard\n          supportLevel: Silver\n          revenueType: SaaS\n      properties:\n        id:\n          type: number\n          description: Internal plan id\n        code:\n          type: string\n          description: Code to identify plan on product side. Corresponds to subscription plan name\n        _ns_displayname:\n          type: string\n          description: Plan display name in english\n        description:\n          type: string\n          description: Description of the subscription plan\n        title:\n          type: string\n          description: Description of the subscription plan (deprecated)\n        isTrial:\n          type: boolean\n          description: Indicate if subscription plan is for trial\n        product:\n          $ref: '#/components/schemas/ProductCoordinates'\n        initialterm:\n          $ref: '#/components/schemas/TermDescription'\n        items:\n          type: array\n          items:\n            $ref: '#/components/schemas/SubscriptionPlanItem'\n        productTier:\n          $ref: '#/components/schemas/ProductTierEnum'\n        productTierTitle:\n          type: string\n        supportLevel:\n          $ref: '#/components/schemas/SupportLevelEnum'\n        revenueType:\n          type: string\n        supportOnly:\n          type: boolean\n          description: Indicate tha this plan is support only and can be upgraded only to another support only plan\n      required:\n        - code\n        - items\n    TermDescription:\n      title: TermDescription\n      type: object\n      properties:\n        name:\n          type: string\n        unit:\n          $ref: '#/components/schemas/UnitTermEnum'\n        duration:\n          type: number\n        type:\n          $ref: '#/components/schemas/TermTypeEnum'\n      example:\n        name: Annual - 1 Year\n        unit: MONTHS\n        duration: 12\n        type: STANDARD\n    ProductCoordinates:\n      title: ProductCoordinates\n      type: object\n      properties:\n        family:\n          $ref: '#/components/schemas/CodeAndTitle'\n        variant:\n          $ref: '#/components/schemas/CodeAndTitle'\n      example:\n        family:\n          code: SOC\n          title: Sococo\n        variant:\n          code: SA\n          title: 'SaaS, the only one, just default'\n    CodeAndTitle:\n      title: ElementPair\n      type: object\n      properties:\n        code:\n          type: string\n          description: Code to be used for identification\n        title:\n          type: string\n          description: Displayable entity title\n    JWTToken:\n      title: JWTToken\n      type: object\n      properties:\n        pfc:\n          type: string\n          description: Product family code\n        pvc:\n          type: string\n          description: Product variant code\n        cid:\n          type: string\n          description: Customer ID\n        padm:\n          type: boolean\n          description: Product Admin flag. Requred for certain endpoints which must be used only by product backend\n        email:\n          type: string\n          description: Self Serve User Email\n    UrlAndAuth:\n      title: UrlAndAuth\n      type: object\n      properties:\n        url:\n          type: string\n        auth:\n          type: object\n          properties:\n            username:\n              type: string\n            password:\n              type: string\n    InvoiceInfo:\n      title: InvoiceInfo\n      type: object\n      example:\n        stripeInvoicePaymentLink: 'https://app.suitesync.io/payments/acct_1KMEYNArxAm3Gt9Z/custinvc/22035055'\n        number: INV9842454\n        date: 13-Jul-2021\n        dueDate: 12-Aug-2021\n        status:\n          code: A\n          title: 'Invoice:Open'\n        totalAmount: 123.52\n        taxAmount: 12.21\n        currency: USD\n        _asofdate: 1-Jul-2020\n        _id: 5846511\n      properties:\n        stripeInvoicePaymentLink:\n          type: string\n        number:\n          type: string\n        date:\n          type: string\n        dueDate:\n          type: string\n        totalAmount:\n          type: number\n        taxAmount:\n          type: number\n        currency:\n          type: string\n        status:\n          $ref: '#/components/schemas/CodeAndTitle'\n        _asofdate:\n          type: string\n        _id:\n          type: integer\n      required:\n        - number\n        - date\n        - dueDate\n        - totalAmount\n        - taxAmount\n        - currency\n        - status\n    Address:\n      title: Address\n      type: object\n      example:\n        line1: 536 Paper street\n        line2: ''\n        city: Bradford\n        state: DE\n        country: US\n        zip: '19808'\n        phone: 111-111-111\n      x-examples:\n        example-1:\n          line1: 536 Paper street\n          line2: ''\n          city: Bradford\n          state: DE\n          country: US\n          zip: '19808'\n          phone: 111-111-111\n      nullable: true\n      properties:\n        line1:\n          type: string\n          nullable: true\n        line2:\n          type: string\n          nullable: true\n        city:\n          type: string\n          nullable: true\n        state:\n          type: string\n          nullable: true\n        country:\n          type: string\n          nullable: true\n        zip:\n          type: string\n          nullable: true\n        phone:\n          type: string\n          nullable: true\n    Customer:\n      title: Customer\n      type: object\n      x-internal: false\n      example:\n        id: SOC-SA-6048b1177cd71936d2234cc6\n        individual: false\n        stripeCustomerAccountLink: 'https://app.suitesync.io/customers/acct_1KMEyNArTAm3Gt1Z/537215/0611239180'\n        individualName:\n          title: Mr\n          firstName: Tyler\n          middleName: E\n          lastName: Durden\n        companyName: Paper Street Soap Co.\n        currency: USD\n        email: tyler@paperstreetsoap.com\n        phone: (288) 555-0153\n        taxIdentificationNumber: ABCDF1234J\n        address:\n          line1: 536 Paper street\n          line2: 2nd floor\n          city: Bradford\n          state: DE\n          country: US\n          zip: '19808'\n          phone: 111-111-111\n        shippingAddress:\n          line1: 17 Sheet street\n          line2: 3rd floor\n          city: Texas City\n          state: TX\n          country: US\n          zip: '12345'\n          phone: 222-222-222\n        primaryContact:\n          name:\n            title: Mr\n            firstName: Tyler\n            middleName: E\n            lastName: Durden\n          email: tyler@paperstreetsoap.com\n          phone: (288) 555-0153\n          billingAddress:\n            line1: 536 Paper street\n            line2: 2nd floor\n            city: Bradford\n            state: DE\n            country: US\n            zip: '19808'\n            phone: 111-111-111\n      x-examples:\n        example-1:\n          id: SOC-SA-6048b1177cd71936d2234cc6\n          individual: false\n          individualName:\n            title: Mr\n            firstName: Tyler\n            middleName: E\n            lastName: Durden\n          companyName: Paper Street Soap Co.\n          currency: USD\n          email: tyler@paperstreetsoap.com\n          phone: (288) 555-0153\n          taxIdentificationNumber: ABCDF1234K\n          address:\n            line1: 536 Paper street\n            line2: 2nd floor\n            city: Bradford\n            state: DE\n            country: US\n            zip: '19808'\n            phone: 111-111-111\n          primaryContact:\n            name:\n              title: Mr\n              firstName: Tyler\n              middleName: E\n              lastName: Durden\n            email: tyler@paperstreetsoap.com\n            phone: (288) 555-0153\n            billingAddress:\n              line1: 536 Paper street\n              line2: 2nd floor\n              city: Bradford\n              state: DE\n              country: US\n              zip: '19808'\n              phone: 111-111-111\n      properties:\n        id:\n          type: string\n          maxLength: 83\n          nullable: true\n        stripeCustomerAccountLink:\n          type: string\n        individual:\n          type: boolean\n          description: 'true for person, false for company'\n          nullable: true\n        individualName:\n          $ref: '#/components/schemas/PersonName'\n        companyName:\n          type: string\n          maxLength: 83\n          description: Required if customer is company\n          nullable: true\n        currency:\n          type: string\n          maxLength: 3\n          minLength: 3\n          description: ISO currency code\n          nullable: true\n        email:\n          type: string\n          format: email\n          maxLength: 254\n          nullable: true\n        phone:\n          type: string\n          maxLength: 32\n          nullable: true\n        taxIdentificationNumber:\n          type: string\n          nullable: true\n        address:\n          description: The billing address, and if not defined separately, the shipping address.\n          allOf:\n            - $ref: '#/components/schemas/Address'\n        shippingAddress:\n          description: The shipping address, if different from the billing address.\n          allOf:\n            - $ref: '#/components/schemas/Address'\n        primaryContact:\n          $ref: '#/components/schemas/Contact'\n    Contact:\n      title: Contact\n      type: object\n      example:\n        id: '321'\n        email: tyler@paperstreetsoap.com\n        title: Mr\n        firstName: Tyler\n        middleName: ''\n        lastName: Durden\n        phone: (288) 555-0153\n        billingAddress:\n          line1: 536 Paper street\n          line2: ''\n          city: Bradford\n          state: DE\n          country: US\n          zip: '19808'\n          phone: 111-111-111\n      nullable: true\n      properties:\n        id:\n          type: string\n          nullable: true\n        name:\n          $ref: '#/components/schemas/PersonName'\n        email:\n          type: string\n          format: email\n          maxLength: 254\n          nullable: true\n        phone:\n          type: string\n          maxLength: 32\n          nullable: true\n        billingAddress:\n          $ref: '#/components/schemas/Address'\n    BaseSubscriptionConfiguration:\n      title: BaseSubscriptionConfiguration\n      type: object\n      description: 'Set of items, quantities and plan for subscription creation and modification'\n      example:\n        planCode: Kayako TNK GROWTH PLATINUM\n        items:\n          - code: Kay-SA-TNK-STA\n            quantity: 25\n          - code: Kay-SA-COL-STA\n            quantity: 2\n        frequency: MONTHLY\n        duration: 12\n      properties:\n        planCode:\n          type: string\n        items:\n          type: array\n          items:\n            type: object\n            properties:\n              code:\n                type: string\n              quantity:\n                type: integer\n            required:\n              - code\n        frequency:\n          $ref: '#/components/schemas/FrequencyEnum'\n        duration:\n          type: integer\n          description: |-\n            Term duration in months. Must be equal or greater than the subscription plan initial term.\n\n            Inform only for creation and renewal. If duration is not informed, the subscription plan initial term will be applied.\n\n            In an update for an active subscription, duration can't be informed.\n          minimum: 1\n          maximum: 84\n    ExtendedBaseSubscriptionConfiguration:\n      allOf:\n        - $ref: '#/components/schemas/BaseSubscriptionConfiguration'\n        - type: object\n          properties:\n            pricingTest:\n              type: boolean\n              description: |-\n                Indicates whether to return the pricing validation information and when it used always return the prices, even if the validation failed.\n                Only possible to be used by super admin.\n      example:\n        planCode: Kayako TNK GROWTH PLATINUM\n        items:\n          - code: Kay-SA-TNK-STA\n            quantity: 25\n          - code: Kay-SA-COL-STA\n            quantity: 2\n        frequency: MONTHLY\n        duration: 12\n        pricingTest: true\n    PersonName:\n      title: PersonName\n      type: object\n      nullable: true\n      properties:\n        title:\n          type: string\n          maxLength: 99\n          nullable: true\n        firstName:\n          type: string\n          maxLength: 32\n          nullable: true\n        middleName:\n          type: string\n          maxLength: 32\n          nullable: true\n        lastName:\n          type: string\n          maxLength: 32\n          nullable: true\n    SubscriptionPlanItem:\n      title: SubscriptionPlanItem\n      type: object\n      properties:\n        id:\n          type: number\n        code:\n          type: string\n        title:\n          type: string\n        type:\n          $ref: '#/components/schemas/ItemTypeEnum'\n        desc:\n          type: string\n        minQuantity:\n          type: integer\n        maxQuantity:\n          type: integer\n          exclusiveMinimum: false\n        required:\n          type: boolean\n        prices:\n          type: array\n          description: Array of prices for frequency\n          items:\n            type: object\n            properties:\n              type:\n                $ref: '#/components/schemas/PriceTypeEnum'\n              frequency:\n                $ref: '#/components/schemas/PriceFrequencyEnum'\n              currency:\n                type: string\n                description: USD by default\n              ranges:\n                type: array\n                items:\n                  type: object\n                  properties:\n                    fromQuantity:\n                      type: integer\n                    price:\n                      type: number\n                  required:\n                    - fromQuantity\n                    - price\n            required:\n              - type\n              - ranges\n        amount:\n          type: number\n        totalIntervalValue:\n          type: number\n      required:\n        - code\n        - type\n    SubscriptionLineItem:\n      title: SubscriptionLineItem\n      type: object\n      properties:\n        id:\n          type: number\n        code:\n          type: string\n        title:\n          type: string\n        type:\n          $ref: '#/components/schemas/ItemTypeEnum'\n        desc:\n          type: string\n        minQuantity:\n          type: integer\n        maxQuantity:\n          type: integer\n          exclusiveMinimum: false\n        required:\n          type: boolean\n        prices:\n          type: array\n          description: Array of prices for frequency\n          items:\n            type: object\n            properties:\n              type:\n                $ref: '#/components/schemas/PriceTypeEnum'\n              frequency:\n                $ref: '#/components/schemas/PriceFrequencyEnum'\n              ranges:\n                type: array\n                items:\n                  type: object\n                  properties:\n                    fromQuantity:\n                      type: integer\n                    price:\n                      type: number\n                  required:\n                    - fromQuantity\n                    - price\n            required:\n              - type\n              - ranges\n        amount:\n          type: number\n        totalIntervalValue:\n          type: number\n      required:\n        - code\n        - type\n    StatusEnum:\n      type: string\n      title: StatusEnum\n      enum:\n        - ACTIVE\n        - PENDING_ACTIVATION\n        - SUSPENDED\n        - DRAFT\n        - CLOSED\n        - TERMINATED\n        - NOT_INCLUDED\n    UnitTermEnum:\n      type: string\n      title: UnitTermEnum\n      enum:\n        - DAYS\n        - WEEKS\n        - MONTHS\n        - YEARS\n    TermTypeEnum:\n      type: string\n      title: TermTypeEnum\n      enum:\n        - CUSTOM\n        - EVERGREEN\n        - STANDARD\n    ProductTierEnum:\n      type: string\n      title: ProductTierEnum\n      enum:\n        - Standard\n        - Professional\n        - Enterprise\n    SupportLevelEnum:\n      type: string\n      title: SupportLevelEnum\n      enum:\n        - Silver\n        - Gold\n        - Platinum\n    ItemTypeEnum:\n      type: string\n      title: ItemTypeEnum\n      enum:\n        - One Time\n        - Recurring\n        - Usage\n    PriceFrequencyEnum:\n      type: string\n      title: PriceFrequencyEnum\n      enum:\n        - ONETIME\n        - WEEKLY\n        - MONTHLY\n        - QUARTERLY\n        - ANNUALLY\n    PriceTypeEnum:\n      type: string\n      title: PriceTypeEnum\n      enum:\n        - Tiered\n        - Volume\n    FrequencyEnum:\n      type: string\n      title: FrequencyEnum\n      description: Billing frequency\n      enum:\n        - HOURLY\n        - DAILY\n        - WEEKLY\n        - BIWEEKLY\n        - SEMIMONTHLY\n        - QUADWEEKLY\n        - MONTHLY\n        - BIMONTHLY\n        - QUARTERLY\n        - SEMIANNUALLY\n        - ANNUALLY\n        - BIENNIALLY\n        - TRIENNIALLY\n        - ONETIME\n        - ENDOFPERIOD\n        - STARTOFPERIOD\n        - CUSTOM\n    AgreementTypeEnum:\n      type: string\n      title: AgreementTypeEnum\n      description: Agreement type\n      enum:\n        - Quote\n        - End User Agreement\n        - Reseller Agreement\n        - Other\n    AgreementStatusEnum:\n      type: string\n      title: AgreementStatusEnum\n      description: Agreement status\n      enum:\n        - Draft\n        - Out For Signature\n        - Signed\n        - Expired\n        - Cancelled\n        - Not Yet Sent For Signature\n        - EchoSign Account Payments Not Up to Date\n        - Other\n        - Out For Approval\n        - Approved\n    AgreementStatusResponseEnum:\n      type: string\n      title: AgreementStatusResponseEnum\n      description: Agreement status response\n      enum:\n        - draft\n        - out-for-signature\n        - signed\n        - no-agreement\n        - no-quote\n    ContractualDocumentTypeEnum:\n      type: string\n      title: ContractualDocumentTypeEnum\n      description: Contractual document type\n      enum:\n        - purchase-order\n    CreateSubscriptionConfiguration:\n      allOf:\n        - $ref: '#/components/schemas/BaseSubscriptionConfiguration'\n        - type: object\n          properties:\n            resellerId:\n              type: string\n            distributorId:\n              type: string\n            contractualDocumentId:\n              type: integer\n              nullable: true\n              description: |-\n                Id of contractual document object.\n      description: Model for subscription create\n    UpdateSubscriptionConfiguration:\n      title: UpdateSubscriptionConfiguration\n      allOf:\n        - $ref: '#/components/schemas/BaseSubscriptionConfiguration'\n    PaymentLink:\n      title: PaymentLink\n      type: object\n      properties:\n        type:\n          type: string\n        url:\n          type: string\n          format: uri\n      required:\n        - type\n        - url\n    Preview:\n      title: Preview\n      type: object\n      properties:\n        frequency:\n          type: string\n        totalAmount:\n          type: number\n        totalListPrice:\n          type: number\n        successPlanPremium:\n          type: number\n        items:\n          type: array\n          items:\n            type: object\n            properties:\n              code:\n                type: string\n              title:\n                type: string\n              quantity:\n                type: number\n              amount:\n                type: number\n      example:\n        frequency: Monthly\n        totalAmount: 110\n        totalListPrice: 220\n        successPlanPremium: 20\n        items:\n          - code: Kay-SA-TNK-STA\n            title: Kayako TNK Standard\n            quantity: 2\n            amount: 90\n          - code: Kay-SA-COL-STA\n            title: Kayako COLLABORATOR TNK Standard\n            quantity: 2\n            amount: 20\n    ExtendedPreview:\n      allOf:\n        - $ref: '#/components/schemas/Preview'\n        - type: object\n          properties:\n            priceIsValid:\n              type: object\n              properties:\n                isValid:\n                  type: boolean\n                  description: Indicates if the price is valid.\n                errorMessage:\n                  type: string\n                  description: Provides an error message if the price is not valid.\n                details:\n                  type: string\n                  description: Additional details about the pricing validation.\n              required:\n                - isValid\n            onlyPlatinum:\n              type: boolean\n              description: Indicates if only platinum plans are applicable. Returned only when previewing a platinum plan.\n      example:\n        frequency: Monthly\n        totalAmount: 110\n        totalListPrice: 220\n        successPlanPremium: 20\n        items:\n          - code: Kay-SA-TNK-STA\n            title: Kayako TNK Standard\n            quantity: 2\n            amount: 90\n          - code: Kay-SA-COL-STA\n            title: Kayako COLLABORATOR TNK Standard\n            quantity: 2\n            amount: 20\n        priceIsValid:\n          isValid: false\n          errorMessage: 'The price is not valid'\n          details: 'Renewal ARR: 100.00, Current ARR: 100.00'\n        onlyPlatinum: false\n  securitySchemes:\n    Token:\n      name: Authorization\n      type: apiKey\n      in: header\n      description: |-\n        JWT tokent signed and encrypted. Can store productFamilyCode, productVariantCode and customerID so results of all requests will be filtered by these values. See JWTToken model\n        ### JWT payload\n          * pfc: string // Product Family Code\n          * pvc: string // Product Variant Code\n          * cid: string // Customer id\n          * email: string  // Self Serve User Email\n    PrivilegedToken:\n      name: Authorization\n      type: apiKey\n      in: header\n      description: PrivilegedToken - same as normal token with padm=true in payload\n  responses:\n    Error:\n      description: General error\n      content:\n        application/json:\n          schema:\n            type: object\n            properties:\n              errors:\n                type: array\n                minItems: 1\n                items:\n                  type: object\n                  properties:\n                    path:\n                      type: string\n                    message:\n                      type: string\n                    errorCode:\n                      type: string\n                  required:\n                    - message\n    PartialResponse:\n      description: Partially successful response. Check errors for failed messages\n      content:\n        application/json:\n          schema:\n            type: object\n            properties:\n              errors:\n                type: array\n                items:\n                  type: object\n                  properties:\n                    path:\n                      type: string\n                    message:\n                      type: string\n                    errorCode:\n                      type: string\n                  required:\n                    - message\n  parameters: {}\n  x-examples: {}\nsecurity:\n  - Token: []\n```\n\n### Response: 200\n```json\nMySight Module review – 2024/09/11 16:58 EET – Transcript\r\nAttendees\r\nAmmar Nofal, Caleb Andrada, Kirill Lanchev, read.ai meeting notes, Rob Austin, Rob Austin's Presentation\r\nTranscript\r\nAmmar Nofal: All good, take it away.\r\nRob Austin: But, okay, brilliant. So yeah, ahead of business intelligence for the last eight years at tivion. So me and my team create dashboards for our customers based on their survey results. So, I work in, Professional Services Department. So our\r\nRob Austin: Our implementation consultants, they help the customers create the surveys and we work with them to decide how that data is going to look on the output. We then work with the customers themselves to say, how they want their data, displayed, what the dashboard should look like. So we often start with the template and we'd say This will be kind of a standard thing and they go. Yeah, I like that bit but I don't like this bit and we need more information about some of these questions and so then we start have a conversation about how the dashboard will then look. So we come with it from two ends, we've got hopefully the finished mock-up, and then we've got the data and then we kind of bring it all together to Create the data source, create the dashboard and make sure it all fits and then we do validation, and qa and that kind of thing.\r\nRob Austin: Dxi creates a default set of tables. And this is basically all based off of the Mysight module. And so we can pick any survey or up to five surveys. We can pick which questions we want to pull out from those surveys. We can decide if we want to use them as filters or just as viewing results. And then we hit the Go button in the mysight module. It's spits out a bunch of tables into exile, which is our analytical database. It also creates. A. Tableau Server Data Source. And it joins all of the tables that it's created into the\r\nRob Austin: prescribed format, basically, with the joins set up as per a template then we get that as a tableau server data source and the reason we do it like this is so that the customers Are then able to create their own dashboards using tableau, if they don't want to use professional services but they don't get access so easily to the raw data. So, it's still within our protected environment and they can only access it through Tableau Server.\r\nAmmar Nofal: No, are you able to show us a quick demo on how all of that works together?\r\nRob Austin: Yeah, absolutely. Let's do that. So Let me.\r\nRob Austin: Bring up.\r\nRob Austin: Share my screen.\r\nRob Austin: Okay, so this is a dxi installation which we just use as our playground. So if I log into this one, it's actually on the sandbox area. So we don't have additional ETL tools, we don't have all tricks available to us in this environment, but we have everything else. so, I would Go into.\r\nRob Austin: maybe we'll start with the project. so,\r\nRob Austin: Here's a demo employee survey. And if we take a quick look at the question set, we can got some welcome things. Go ahead if we do a preview of this, We can see what this survey looks like. Employee survey. I would recommend on. So somebody has already filled out this to each of these questions.\r\nRob Austin: We're then going to use this Mysight module to pull out the relevant, questions to us and put them into a useful format. So, I'm going to pick my side project. Let's call this.\r\nRob Austin: A site. Which as you can see, we've done many times before.\r\nRob Austin: That's fine. and then, in here, I'm going to\r\nRob Austin: Pick an EFS project. So it's called Demo employee survey. So that's the one we were looking at. I can add another one, If I wanted to look at demo employee survey too, and then we could do year on year calculations comparing one survey to another and that kind of thing. So in here, I then pick, whichever questions I want. To hit our hands. Fat. Maybe we'll do everything.\r\n00:05:00\r\nRob Austin: Just looking at the types of questions, we've got it. Yeah.\r\nRob Austin: okay, and these are basically\r\nRob Austin: Sets of questions from the survey. And if I want to, I can turn one of these into a\r\nRob Austin: I could turn one of these into a dimension. So this would then allow me to use it as a filter and that just changes the shape of the data model slightly in the background.\r\nRob Austin: So this is the question said itself. We can then also add some metadata about the survey. So something I often put in is date of last access. That is basically the date when the respondent completed their survey. And again we might want to filter by this. So we can set as a dimension. participant data or don't think we have much in here but potentially we capture Metadata about the participant. And this is usually provided to us by whoever is setting up the survey. So if we're running an employee survey for British Airways, then they would give us information about their participants, and we would put that in the survey metadata Organizational structure. This is to do with the hierarchies.\r\nRob Austin: So again, a big organization will have a hierarchy starting at CEO and going all the way down to their lowest level of workers. And so we might bring in the organizational structure into here.\r\nRob Austin: Field report is really to do with the response rates. What? Percentage of people have completed this. We don't use this very often. It's very limited in its capabilities, and we have other more bespoke ways of getting that information. And then we have something called action planner. This is an add-on survey, which Customers can use to generate actions. For example, If I look at my data set and I can see that it's\r\nRob Austin: There's a problem and an area and I want to take some action, I can click through onto that I can generate an actions, puts it in a ban board and then we can monitor those actions a little bit like JIRA. but again, we can do dashboards based off of that if you were to create a custom dashboard off of JIRA, except we can put it into anywhere we like\r\nRob Austin: So this is the mysight module survey side. This access control is to do with the audience of the dashboard. So this is probably a different set of people to the people who are participating in the survey. Sometimes it's the same but often it's different. So that is administrated in this people module here. And we can set up the groups, so if there's any copy of my site, user has 24 people in it. And we can actually get some metadata about these people as well as we've got their name probably email address. We can add this kind of information in which might help us with any more complex roll-up security that we need to do or anything like that.\r\nRob Austin: We've also got these configurable fields master data, which is further information about our audience. So it might be like if we want to add something where they sit in an organization or maybe where they live, so that the rest, we can restrict the data down to those additional metrics as well. so, once we're done with setting it up, We click the Go button.\r\nRob Austin: I got a message just now saying that Tableau server was not available and that may be the case because it's a sandbox environment. that I'm showing you we don't use it very often. But that is possible, but hopefully this will work and we'll set us up a tableau server data source.\r\n00:10:00\r\nRob Austin: While we're waiting, I'm going to start up Tableau server on my local machine. what when we do real customer projects, it's not in the sandbox environment and we don't tend to work Off of our local machines, we've got workspaces set up in AWS so that we can actually get the data in the database if we need to. So, it's a very contained environment clients can't get into that, it's only. Within tivion or trilogy that anyone would ever have access. To that one.\r\nRob Austin: I'm just going to check the logs here to see if anything's actually happening in the background.\r\nRob Austin: Yeah, now we're moving. That's good. so,\r\nAmmar Nofal: And actually for new created installations, are there any specific configuration that you need to do other than My Site settings?\r\nRob Austin: So, because a brand new customers for brand new installations? Yeah, it tends to support that sets that up for us. I've never set up a brand new installation. I only have worked on existing ones.\r\nRob Austin: \r\nAmmar Nofal: And are you familiar with the backend code for this or repositories?\r\nRob Austin: \r\nRob Austin: So I've never seen it in theory. I know, kind of where it sits and that's sort of thing. So, My understanding is that. The databases are Maria, dB in the background and there isn't something they call an intermediate database. Which is used kind of for staging for my side. So I think this process Puts it into an intermediate database and then pushes that into Exosol. That's as I understand it but I never seen any of that code. I'm afraid.\r\nAmmar Nofal: but,\r\nRob Austin: Okay, it seems to be doing something. And I've been there.\r\nRob Austin: Failed to. So this works. Maybe a month ago.\r\nRob Austin: That when did we last set this up? It's saying it hasn't got a connection to Tableau server. So I'd only ever look so a month ago, I created this one that worked fine. Some of these broken, I would probably raise a ticket and say, Hey, my environment is broken and then hopefully somebody would either work with me to fix it or they would be able to take care of it. But that's not an area that I have any knowledge of I'm afraid.\r\nRob Austin: This is a installation which we use for demo is but this actually sits in our live environment. So we might have a little bit more success in this.\r\nRob Austin: yeah. Okay. So\r\nRob Austin: So yeah, we can see I won't create a new one again because I've shown you the process for that, but We've got. This test sandbox connection RV. Not sure what it is, but let's have a little bit of a look.\r\nRob Austin: so, I'm just gonna bring Tab, over here. Can you see that one? Okay.\r\nRob Austin: Do you see tableau or do you still see a\r\nAmmar Nofal: We're still on my side tank.\r\nRob Austin: okay. You don't see Tableau right? Let me, yeah. Okay. Let me\r\nRob Austin: Stop that one.\r\nRob Austin: And in fact, what, I'll jump into my workspace. As I only have it open.\r\nRob Austin: Yeah, once again.\r\nRob Austin: where is it? That you guys work, which section?\r\nAmmar Nofal: Mastery come again.\r\nRob Austin: Where do you guys work? Which department? Okay. …\r\nAmmar Nofal: Engineering actually.\r\nRob Austin: you're trying to take over My site code base. Okay, make sense.\r\nAmmar Nofal: Yeah.\r\n00:15:00\r\nRob Austin: All So I don't know if you've ever seen it before, but this is Tableau So, if I Sign into.\r\nRob Austin: Different site here. So that was the installation name.\r\nRob Austin: And if I, Connect to some data.\r\nRob Austin: We should be able to see. That one, which was called. Rv. I think it was called that.\r\nRob Austin: There we go. So, test sandbox connection of the\r\nRob Austin: So, that should in here.\r\nRob Austin: no. Sorry that's the one connection. Let's try S Company dashboards.\r\nRob Austin: It's not that. All right, let's just I'll pick one random.\r\nRob Austin: Let's testing.\r\nRob Austin: It does not respond, but that's okay. We can edit the one which does work.\r\nRob Austin: Okay, let's try that one. No, it doesn't matter either.\r\nRob Austin: One. Yeah. Okay.\r\nRob Austin: Not sure what we all have modified dates, the same as well. Some of this stuff you really old and might just not work anymore. Let's try this one.\r\nRob Austin: No, nothing.\r\nRob Austin: Okay, instead then show you a project which I'm currently working on. so, this is\r\nRob Austin: A data source. It's not the standard one. It's one that we've crafted a little bit but Should have the same sort of idea in here. So we've got a bunch of questions.\r\nRob Austin: Yeah, they're getting question hierarchy.\r\nRob Austin: Yeah, so we have some questions in here.\r\nRob Austin: And we've got some responses. And so here's basically a question set.\r\nRob Austin: And then we can start to interrogate. each of these, it's just\r\nRob Austin: learn to color. And let's just pick a couple of these questions that are a bit simpler. As you can see, survey data can be pretty. Diverse in how it looks, of it's never the same. There's no standardization to it. Somebody can create any question they want with any scale they want. So then putting that into a standard dashboard can be challenging. But we do have templates that we use and can make it a certain way. So now if we go to a simple,\r\nRob Austin: Like that. Then we can see that. We've got.\r\nRob Austin: number of toes three's fours. There's not a great data set unfortunately, but we can see how this breaks down and typically I think five is likely to be I strongly agree or something like that. And so we have a large portion of those and then we can do things like add the label in there. We can say, Okay, what's this look like as a percentage?\r\nRob Austin: And so then we can see, What 17% of my user base to this question? Answered with a five and maybe actually we want a group force and fires together. So we can go ahead and do that. So once you get your head around the data, you can very quickly manipulate the data into, the way, you want to see it, maybe we want to group the ones and the two as well. Something that customers often ask to turn that Into a three-point scale. So then we have good medium bad basically. And see that's not adding up to 100%. Let's just make sure how that's working computing table across.\r\n00:20:00\r\nRob Austin: That's a bit better. So yeah, this is the type of thing. that me and my team do we create these dashboards for the end user but yes, I do have a lot of experience using my site, but I don't have any backend experience and I'm afraid\r\nAmmar Nofal: Yep, that's good. I believe you provided us with everything regarding the front end or are there any other information that you'd like to add?\r\nRob Austin: So, we Probably something that's worth pointing out. Is that this is exersol?\r\nRob Austin: So here, I've got each of those schemas. So this was the one that I tried to use cm0955 which Through errors for whatever reason. But it looks like we do have tables in there and These are fairly Tables. I don't know where this number comes from this. Long number it's very inconvenient because it pushes everything off to the right? But basically this number 836 will be the same for every table. Within this s for a bigger difference schema then that will have its own one fa3 identifier.\r\nRob Austin: But yeah so all of these always the same anything that's different is a custom table created probably by me or my team and we will then join that into the data model.\r\nRob Austin: The data model is reasonably standard out of EFS. It's always joined in a certain way. It always starts with the fact table tends to be a star schema with a bit of a snowflake to it. But in essence it's a Kimball methodology. type of data model that is created and I believe it does this from a template\r\nRob Austin: let me show you Tableau server.\r\nRob Austin: So, this is the production. Server.\r\nRob Austin: and again, let me go back to that other one I was on CM and 955.\r\nRob Austin: And in here, we've got projects and within each project we'll have a Mixture of data sources. And workbox. So, anything that is owned by technical support was created by EFS. And these data sources are basically Within a schema essentially. And again, it seems to like it's broken but maybe just something that we can fix. This is an old exosole server actually, so it's looking for something that no longer exists. Maybe you're probably aware. We did our AWS migration.\r\nRob Austin: Earlier this year and pretty much everything was migrated, but there may still be some content that is pointing at old servers or old databases and needs to be moved across. We moved everything that people would want, but some of the old unused content, it seemed like a waste of time to do. So We prioritize the customers, then the live demos, and then anything else that we thought would be useful and just the stale content, just got left. we're intending to take on a project to clean up the server and whether that means we fix some more of these or whether that means that we just Delete it without things that are not needed. Now, probably happening in Q4 this year. I imagine\r\n00:25:00\r\nRob Austin: So yes, table. Let me pick Something that I know does have content. That works.\r\nRob Austin: so, I finally\r\nRob Austin: Yeah, we can see there's a whole bunch of dashboards in here that have been created over the years. Or maybe different versions of the same dashboard and then we've got a bunch of these data sources as well. So if I look at one that was created by ten minutes support. This should be a standard one. And ask data is a preview of it. Looks like it's not going to work. For whatever reason seems to be a common theme for today.\r\nRob Austin: Let me do a new. Workbook using that data source. This is the online version of tableau, it doesn't have as many. Capabilities. As the dablo desktop that I was using just now, but you can do pretty much the same thing. So again, if I pick that question hierarchy, To question. Do you responds? I think we've got languages set up here. so,\r\nRob Austin: if I decide, I just want this in English that will get rid of a load of those What did I do before? I did.\r\nRob Austin: It's your value. that's,\r\nRob Austin: Again, and I'll just keep a couple of these. but exactly the same thing as before, say,\r\nRob Austin: This is a really similar environment to the other one. We can create a dashboards.\r\nRob Austin: Basically, you could create all your sheets and then you put them into a dashboard and then you interact between the two and you can float images over and then you start to make them look all nice and sexy and something that the customer wants to see.\r\nRob Austin: the only piece of the puzzle I haven't showed you was how we create these so we can either script them in SQL. Or we have a tool called Alterx that we can use, which is an ETL tool. So, here, for example, I'm just taking a fixed set of data and pushing it into exercise. Probably don't need to use an ETL tool for that but I did. So we can then set this up to run on a schedule or we can set it to run so that any of my team can pick it up and use it. But that's basically, one of the ways that we can get these bespoke tables into our schema. I'm not sure how much that affects you guys. I imagine all your work will be\r\nRob Austin: Up to this bit Really creating these tables from what we call Dxi.\r\nAmmar Nofal: And are there any performance buttons that you are aware of?\r\nRob Austin: do you mean dashboard performance or do you mean data source creation performance?\r\nAmmar Nofal: Yes.\r\nAmmar Nofal: More of data source. I'd say creation performance.\r\nRob Austin: I think we were doing one earlier. so Maybe this one here. Refresh so that I was working with the colleague earlier to live project and we reset it and probably you can see that. I reset that at 140 my time. And then we waited waited. And it wasn't until\r\nRob Austin: 10 minutes later that it actually started pulling data in. and there are Chron jobs that run in the background that basically trigger this kind of thing, and I feel like that could be optimized I don't see why we need to up to 10 minutes for it to know that something is needed, and to kick it off. so that would be one. performance, blocker, I would say\r\nRob Austin: Because we've upgraded exersol I suspect that we can improve the performance of this probably just with configuration quite a lot. I think it used to be we didn't want to overload the database with too much data coming in because it might hurt the performance of reading the data on the way out. But I don't think that's the case anymore. I think we can be quite aggressive with putting data into the database.\r\n00:30:00\r\nRob Austin: Yeah, as other sort of thing you meant that one. Okay. Yeah,…\r\nAmmar Nofal: Yes, exactly.\r\nRob Austin: And this would be great if we could get rid of this time delay, that would be amazing. and in terms of the performance of the dashboards themselves, they're actually pretty good these days since we upgraded to AWS the performance have got a lot better. But if the performance is bad, that's when me and my team start looking at the data models, and maybe we need to aggregate data for the customer or something like that. So we tend to take care of that for the customer side of things.\r\nAmmar Nofal: That's good. Thank you ob. I believe I don't have any questions from my end Carol or…\r\nRob Austin: No problem.\r\nAmmar Nofal: Caleb. Do you have any questions?\r\nKirill Lanchev: Not on my side.\r\nCaleb Andrada: Nothing. Yeah.\r\nAmmar Nofal: Okay, then, I think Rob we can wrap this up. Thank you very much for your time. And have a good rest of your day.\r\nRob Austin: Yeah, no problem. If you have any questions, Yeah, and yeah, if you got anything else,…\r\nKirill Lanchev: Thank you.\r\nRob Austin: just reach out.\r\nAmmar Nofal: Absolutely, cheers.\r\nRob Austin: Thanks everyone.\r\nAmmar Nofal: Take care. Bye.\r\nCaleb Andrada: Here's everyone. Thanks.\r\nMeeting ended after 00:31:35 👋\r\nThis editable transcript was computer generated and might contain errors. People can also change the text after it was created.\n```\n\n### Response: 200\n```json\n00:01 - Speaker 0\nHello everyone. And welcome. I'm excited to spend some time chatting about contently with you all. Thank you so much for being here and taking time out of your day. Okay.\n\n00:15 - Speaker 0\nSo just by way of introduction. Hi, my name is Ashley Allen. I am the head of product here at Contently. Great to meet you all. And I appreciate you taking time out of your busy days.\n\n00:26 - Speaker 0\nI wanna tell you a little bit about what we're going to do today during the demo. 1st, I'm going to walk through a few of our slides to help better help you better understand Contently and what we offer. Then I'm going to take a high level demo tour through our product. Then I will come back and share some of our customer stories and the results that we drive. Okay.\n\n00:52 - Speaker 0\nSo let's talk about Contently. So Contently started over a decade ago, really before content marketing was even a job title. And the benefit of that is that Contently essentially has evolved and grown to meet the needs of enterprise content marketing teams. Our mission is to ensure our clients have successful content, both now and for many years to come. Our offering is an end to end solution, and that means you can do everything from strategy, execution, analysis, all can be achieved on our platform.\n\n01:30 - Speaker 0\nSo how do we deliver these results to our customers? So really, Contelly isn't just providing you a bundle of all the tools that you saw on the previous slide. Our foundation is based in the product in these three pillars, services, talent, and technology. 1st, we have our global creative marketplace, which consists of a 165,000 registered freelance talent from all over the globe. This is a highly vetted global community of award winning content creators to really help support the creation of any content imaginable.\n\n02:07 - Speaker 0\nSecond, we have our content creation services, supporting strategy and content creation operations. Whether you're looking for a managing editor to manage your operations, an art director to help with imagery, a dedicated content strategist, or an SEO specialist, we have those specialized experts in our network ready to support you and your staff as you need them. Finally, we empower you with our content marketing platform that makes all of it possible. The Contently platform is really mission control for your content operations. You can document and align your teams around your strategy, ideate and collaborate on content ideas, manage your content calendar and plan your your content plan, and optimize your content for better performance.\n\n02:53 - Speaker 0\nIt all comes together here, and I will be showcasing that to you in a few minutes. But let's dive into the depth and breadth of the global creative marketplace. If you need a subject matter expert, say you're looking for a freelance writer who's aware of complex hacks law, or you need someone with scientific research background, or a talent or a travel guru, we really have that here and everything in between. So don't hesitate to leverage our network of expertise to to exemplify what is important to your brand. Now what we hear most often from our clients is that they're really trying to scale their content programs.\n\n03:33 - Speaker 0\nThey may be producing 1 to 2 pieces of content per month, but really they wanna scale up to 5 or 6, for example. And really there's no limit to how much content you can produce with our freelance network. Really, it allows you to cover ground on as many topics that are important to you, your audience, and your marketing goals. But we don't just stop at written content. We know your audience is consuming content on your blog.\n\n04:01 - Speaker 0\nThey're consuming multimedia content in a variety of channels, and you need to meet that audience wherever they are. So whether you need a copywriter, editor, videographer, podcaster, photographer, graphic designer, we have an array of profiles at your disposal. And so if you can dream it, we can help you create it. And let's talk a little bit about the platform because this is really where the magic happens. Our platform is an AI driven comprehensive content solution.\n\n04:35 - Speaker 0\nThe platform was designed and has evolved to support common pain points, such as organizational silos, lack of strategic alignment, quality control needs, and lack of resources. All of this leads to content chaos. And that's what we're gonna help you eliminate and leave behind for 2024. So let's walk through the platform. I'm going to highlight how we can improve your strategic alignment by centralizing your strategy, how you can supercharge your content programs velocity with our workflows and collaboration, And finally, ensure that you are producing top notch quality with our optimization tools for SEO, brand compliance, and organizational compliance, as well as managing your content performance with our robust analytics suite.\n\n05:25 - Speaker 0\nOkay. Bear with me as I move over to our demo. Okay. Alright. So before I jump into the product, I wanted to show you the content strategist.\n\n05:50 - Speaker 0\nThis is our foremost content marketing blog that helps every helps deliver everything from thought leadership to how to articles within content marketing. And I welcome you to review this at any time, but really the reason why I'm showing this to you is because this helps you helps demonstrate what the platform could do for you. Everything that you see in this blog was created in the Contently product. So without further ado, let's jump in. Now I'm gonna take you on a journey through the product from beginning to end.\n\n06:22 - Speaker 0\nWe'll talk about the content strategy. We'll go through talent sourcing, ideation, planning, creation, management, distribution, and analytics. So let's start with the content strategy. As content marketers, we know the content strategy is the pillar of everything that we write. So within Contently, we we encourage you to centralize it on our product because once you've centralized the content strategy incontently, it can help power both the people in the platform and the the tools that we have in the platform to ensure that everyone is on the same page around what goals you're trying to achieve and producing content that meets those goals.\n\n07:04 - Speaker 0\nSo first within goals, this is a fully customizable form that essentially allows you to determine what your primary goal is, your organization type, define your content mission, provide your KPIs, and even upload something like a brand guide for instance. In addition to the goals, we also have, areas where you can input your audiences. So you can create those audiences and, again, fully customize those. You can have as many as you need as well as pillars. And pillars are thematic elements of your value proposition that you may be that you may need to speak to to your audience.\n\n07:42 - Speaker 0\nNow what's great about these is that they come through in all almost all aspects of the product from talent sourcing to creation as well as analytics. So once you populate your pillars, your audience, and your goals, you can start to plan your content, around these goals and ensure that you're really meet meeting all of those, pillars that you've outlined as well as the audience that you've defined. We also allow you to upload your SEO keywords into the product. Again, this is a great way to centralize those keywords in one place, but also empower those tools and people in the product that are creating content on your behalf. Here you have a list of keywords, number of results, search volume, as well as cost per click, information to help you optimize your SEO strategy.\n\n08:34 - Speaker 0\nK. That's a high level view of the content strategy tools we have. I'm gonna jump over and show you how you can start to source talent within the Contently network. So the first tool, that we I wanna share with you is our intelligent talent recommendations. And as I mentioned, the content strategy that you enter will really build a lot of relevance and quality throughout the experience.\n\n08:57 - Speaker 0\nAnd the first way that we do that is with intelligent talent recommendations. This list of freelancers is really derived from your content strategy and pieces of content that you've produced in the product. And when you've got these recommendations, you can take a sneak peek at these writers. You can understand their headline, their bio, can view relevant stories. You can even view their portfolio on the content.\n\n09:16 - Speaker 0\nRelevant stories. You can even view their portfolio on the Contently platform. And if this person is something that you're interest is that this person is something you're interested in, you can click on this button and you can invite them to pitch, essentially start exchanging ideas with them on the platform, or you can just invite them to your team. And when you invite them to your team, you can start staffing them on content. However, if the intelligent talent recommendations aren't delivering the talent you're looking for, you can always do a, a talent search.\n\n09:46 - Speaker 0\nSo you create talent search and you define all of the parameters you have for that talent resource. And once you've done that, that those resources will again show up on this page. And just as before, you can, you know, add them to your team, invite them to pitch. However, if none of this really meets your goals, you can create a custom talent request, which essentially reaches out to Contently Resources to help you find the bespoke talent resource that you're looking for. Now once you've staffed your team, you can start to generate ideas with that team.\n\n10:21 - Speaker 0\nAnd there's a 3 different ways that we do that within the Contently platform. 1 is with pitches, the other is SEO story ideas, and last but not least, content requests. So I'm gonna walk through all three of these. So within pitches, there's really two ways that you can initiate pitches. If if you have an idea yourself, you can create a pitch and submit your idea to your content marketing team.\n\n10:44 - Speaker 0\nHowever, if you're looking to produce content on a very specific topic, you can create a pitch request. And that will go out to your internal writers or the freelancers that you've sourced from the Contently team and start to generate ideas from, that team of writers or freelance creatives, whatever content you're looking to produce. Now when you have a pitch in here, it's it's great to have it in the product because it's completely streamlined. You can have commenting and messages back and forth to mature that idea. You can even if you accept this idea, you push it into a story, and it's ready to go for creation.\n\n11:18 - Speaker 0\nIt pipes right into your production operations. Next, we have SEO story ideas, and this is really a great way of identifying the white space in your SEO keyword strategy. What this is is an algorithmic recommendation of story ideas based on the keywords that you've updated and what people are searching for. So what are what topics or content are people looking for online that are relevant to your SEO keywords that you may not be hitting with those exact keywords? So it really helps you reach those, customers where they are and deliver topics that they're looking for.\n\n11:57 - Speaker 0\nNow what we see with our SEO story ideas is a 76% acceptance rate of these ideas. So we know that these ideas are really hitting the mark for our content marketers. Next, we have content requests. As content marketers, you know ideas come from everywhere and you have many stakeholders who are requesting content for their individual needs. So centralizing all those requests in one place is the key benefit here of the content requests forms.\n\n12:26 - Speaker 0\nSo you can create these forms for different teams and you distribute that to to everyone within your organization so they can submit your their ideas and essentialize here. So as the content marketer, you can turn that chaos of ideas coming through Slack, through email, through Teams, and have all those ideas right here so you can prioritize the different ideas, identifying any duplication of requests, any requests for content that you've already produced, all of that can be managed here. You can also accept or decline these ideas in one centralized location. Right. So that is ideation.\n\n13:05 - Speaker 0\nI'm going to jump over to planning. And, of course, no planning tool is complete without a calendar. And the Contently calendar is really our users' most one of our users' most favorite features. And the reason for that is it goes above and beyond a typical calendar that you may have. 1, these cards are custom built to display the information that is most relevant to you, the content marketer.\n\n13:29 - Speaker 0\nSo we tell you if there's anything overdue, what type of content you're producing, what is the headline, who's on point for this step, what step they're in, and how much progress you've made against that workflow. So it's a really quick way to identify the status of your program at a at a bird's eye view and make adjustments as needed. And if you need to move any dates, you can easily drag and drop those stories to different dates. But one really powerful feature of this is as we work in enterprise organizations that are fairly matrix, there's a lot of different teams that may be producing content. And you may need to coordinate across those teams to ensure that you're not duplicating efforts or potentially dropping the ball somewhere.\n\n14:12 - Speaker 0\nSo within Contently, you have the idea of instances so you can quickly at a glance see what different people are producing in their instance. So as you see, I'm adding some publications here, and new cards are appearing that are color coded for that specific publication. So all of that is managed within the content calendar, and it's a a really great way to keep track of of your meeting your goals of content production as well as collaborating with your teams within your organization. Okay. So let's go ahead and jump into content production.\n\n14:49 - Speaker 0\nSo within Contently, we have a lot of really great features to support the creation of content. So one thing there's there's one major differentiator that our tools have when compared to say Google Docs or Word Docs. When you're working with Google Docs or Word Docs, generally speaking, you're looking at, collaboration, version history, as well as commenting. These some of the these are some of the core features that you need within those products to really solicitate sorry, solicit feedback from, your internal teams. So I'm gonna show you how we meet those needs within the Contently platform.\n\n15:27 - Speaker 0\nSo commenting is super easy. You can highlight any piece of, copy here, and you can annotate your comment. You can, at mention or tag any user within your organization, And you can have a dialogue back and forth with those comments. You can maintain a history of all those comments. Look at both the open comments and the resolved comments for future reference.\n\n15:52 - Speaker 0\nAlso, we have a very robust version history tool. So right now, we're looking at the current version. But if I wanted to go back a little bit, I can see which version number that is. I have a time stamp of when it was, created, and I also have an owner of that version. And when I compare those versions, I scroll down, I can see the content that was added, the content that was removed, and keep track of all of those changes.\n\n16:16 - Speaker 0\nSo I know this is something that you you may use a different text editor for, but where it contently goes above and beyond is, with our requirements tab. Now the requirements tab is a great way to maintain awareness of the objectives of that story. What are what are you trying to convey? Who is the audience? And what is the goal of this piece of content?\n\n16:40 - Speaker 0\nAdditionally, all that information that you've uploaded into the content strategy is right here, just a click away, and your writer's producing content can easily reference that. And what we've heard from our customers is having all this information at the ready essentially reduces the number of versions that you're creating from say, you know, 10 versions down to 2 versions. So maintaining that strategic alignment in the forefront really drives a lot of meaningful results for your organization. We also have this review tab that helps ensure that you're meeting your quality and guidance within your organization. So within quality, you can see examples of where we have, misused words, any example of passive voice, for instance.\n\n17:26 - Speaker 0\nAnd then in the optimization tab, we can make recommendations for the story. So for instance, what is your reading time, your character count, and the SEO keyword selection that you've added? It will tell you if it appears in the headline, how often it's in the body, or in the subheader. So you can start make making optimizations to this content. It will also tell you if we're missing all texts as well.\n\n17:47 - Speaker 0\nSo all of these tools ensure that you're re meeting your brand compliance. I also wanna talk a little bit about how you how you can manage the workflow of the content creation. So our workflow is really purpose built for creation of content. It works alongside with any project management tool that you have within your organization. But the the intent of the workflow is really to manage the handoff between one collaborator to another.\n\n18:17 - Speaker 0\nSo within here, you can see there's an owner of that, workflow step. There's a description of what needs to be done as well as due dates. And we also have a payment, option in here. So if you are paying our freelancers, you really don't have to worry about additional paperwork. Once that story is completed, you can pay that freelancer straight away.\n\n18:39 - Speaker 0\nAdditionally, as you're working with multiple people in your organization, this workflow essentially makes sure that everyone has editing access when it is appropriate for them. So you may need your your subject matter expert to be one of the first people to weigh in, but your legal team to be one of the last people to weigh in. So all of that is managed through the workflow. However, if you do wanna work concurrently, we do have a a new collaboration feature. So I'm going to move to a different window and start typing in a different window, and you can see that information is here in real time to boost that real time collaboration with different writers as well.\n\n19:16 - Speaker 0\nSo you can designate the real time collaboration or manage the work manage the editing through the workflow itself. Last but not least, a lot of our customers are from highly regulated industries, and it's really important for them to keep track of the changes of the document for any auditing purposes. So in addition to the version history and maintaining all the comments as well as the workflow to track approvals, you have your activity log here that highlights every step of the process, who's made comments, who's manually transitioned steps, who's submitted stories. All of that is a time stamp with the user, the action, and the time. And that is something you can download and share with anyone in your organization anytime you need to audit your content.\n\n20:03 - Speaker 0\nOkay. So that is creation. I am going to talk a little bit about how you start to manage this content because what we've heard from our prospects is you can produce, you know, a few pieces of content a month, but when you start to produce a high volume of content, it becomes very difficult to manage the different teams and the different content running through your your team. So within Contently, we've thought a lot about this, and our tasks redesign really helps serve 2 different users' needs. The first user is anyone on your team who's really sort of an individual contributor to the content.\n\n20:34 - Speaker 0\nMaybe they have one job within a story, or 2 jobs, but really, they just need to come in, get the work done, and leave. So when they come into Contently, they're going to see this task page. And if they click on on this, they'll be taken directly to that page where they can start their job and get, and finish that as quickly as possible. So this acts kind of like a to do list for them. However, we know a lot of content marketers act as air traffic control.\n\n21:01 - Speaker 0\nYou're managing the different stories you have in the in the platform. You're ensuring you're meeting your deadlines, and there's a high volume. So it's really important that you keep track of everything. So publication task gives you a high level view of what needs your attention. What is overdue?\n\n21:15 - Speaker 0\nWhat have you put on hold? Are are any steps unassigned? And what is ready to publish? And that's just at a glance. Last but not least, you can come to the activity tab and see a play by play of all the activities happening, with your content in the platform.\n\n21:35 - Speaker 0\nAnother really powerful tool we have for a management of high volume of content is our campaigns. Once we see our customers producing a certain volume of content, campaigns becomes one of their favorite features. And this is because it allows you to create a campaign where you can set a specific goal or objective against that campaign as well as a a a timeline against that. So within Contently, we are working on a few things like, our social media, for instance, or our content refreshes. And so we have a a goal of 19 stories, and we can see the progress of those of those stories.\n\n22:09 - Speaker 0\nWe've completed 10 and 8 are in progress or overdue. And we also here have, built in analytics around the performance of that specific campaign. So it's a really great way to to create a subset of content that you need to track the progress and performance against. Alright. Now I'm gonna jump into integration.\n\n22:30 - Speaker 0\nSo at Contently, we know that you have a variety of tools that you're working with within your organization. And I'm sure the first thing you're thinking is your CMS. How do you get content out of Contently and into your CMS? So we have out of the box integrations with Adobe Experience Manager, Drupal, WordPress, and we also have a custom integration which supports most other CMS tools that you may have. We also integrate with the major social channels, as well as a Salesforce integration that allows you to surface the content that you have in Salesforce so your team can use that to nurture their leads.\n\n23:07 - Speaker 0\nWe also have a custom API for anything else that you need to do. And we are investing heavily in expanding, our integrations for 2024. The next focus we have is project management tools, and then we will also round out our CMS tools and provide many other integrations. Okay. Let's shift over to analytics.\n\n23:31 - Speaker 0\nSo we understand that most organizations are using Adobe Analytics or Google Analytics as our source of truth, and we're not trying to replace those tools. We're really trying to provide supplemental information that is critical for content marketing teams that maybe wouldn't be surfaced through a sort of a web analytics tool like Google Analytics. Now the first area is around production. How are your content operations doing around the the volume of content that you're producing? And we have, dashboards like stories completed by day, average price per story, who are your who are your, most productive contributors, how is performance against those contributors, all of that is within the view.\n\n24:18 - Speaker 0\nWe also have custom built dashboards specifically for performance metrics, like brand awareness and lead generation. So these dashboards are built for you to to take a look at those specific metrics to help inform how your content is doing against those goals. And these dashboards are customizable. You can drag and drop them. You can add new cards.\n\n24:40 - Speaker 0\nYou can remove the cards, all really to support your needs and getting information as quickly as possible. We also have a tool called Docalytics, which essentially provides a heat map of any hosted document that you you that you publish through Contently. So what this provides is an engagement score by page, tells you how the readers are dropping off in your content, and really what content are they focusing on. So you can produce better content going forward. Last but not least, we have the content value tracker.\n\n25:16 - Speaker 0\nNow the content value tracker is a great way for you to demonstrate to your leadership team the value of content marketing. Unlike paid media, which essentially is a flash in the pan, if you spend your money, you see the results within a few weeks. Really, content marketing pays dividends over time. So once you produce a story month after month, it's going to deliver results to you in terms of traffic. And what is the value of that traffic to you?\n\n25:39 - Speaker 0\nWell, what this chart is telling you is how much you would have had to pay in search engine marketing to drive those same results in terms of of, traffic to your site. So as you can see, Contently is moving from, up up into the right because of the more content we produce, the more value we deliver to our organization. Alright. Now that concludes the platform demo. Okay.\n\n26:11 - Speaker 0\nSo let's talk a little bit about case studies. I don't wanna tell you we're great. I want our customers to tell you that we're great. So the first one we'll talk about is Coast Capital. They are one of our powerhouse users.\n\n26:22 - Speaker 0\nThey came to Contently looking for an all in one solution to hone their content strategy and production while heavily focusing on organic SEO. They needed to keep their customers up to date during crucial times and updating their content program was the main vehicle for that relationship with our customers. As you can see, Coast Capital increased our production from an average of 20 assets to over 400 assets and counting. So they're really able to meet the demands of their content organization. Not only that, but they also increased their average time on page from 7 to 15 minutes.\n\n27:02 - Speaker 0\nAnd they knew that their customers were also engaging with multimedia content. And this ultimately resulted in the 1st page ranking on search engine results page, which really, again, underscored the performance of this program. The full case study can be found on our website if you would like to learn more about this. And we also wanted to look to g 2. G 2 were really proud to be a leader in g 2.\n\n27:29 - Speaker 0\nUnlike most pay to play awards, g 2 really puts our customer reviews front and center, and we are so proud of our clients. We're honored that they are consistently show their appreciation through g 2. And those are customers like Dell, American Express, Marriott, and Synchrony to name a few. Alright. So that concludes the presentation portion, and I would like to stay on for some any questions that you might have.\n\n27:57 - Speaker 0\nBut I also would like you to subscribe to the content strategist. Follow us on LinkedIn. And if you have any questions, reach out to us at marketing at contentlink.com or drop us a line. Okay. So if you have any questions, please add them to the chat now.\n\n28:22 - Speaker 0\nOkay. It looks like we have a question here. How does Contently support AI features or AI content production? That is a great question. So at Contently, we firmly believe in the power of AI.\n\n28:36 - Speaker 0\nWe know that AI is really going to, accelerate the pace of content production and really help content marketers become more efficient. And we have a lot of features on the road map in 2024 that will help accelerate the pace of that content production. However, we strongly believe that a great content marketing program needs authentic voices and and expert opinions. So that is still something that is coming from people. So how do we make those people more effective at that work?\n\n29:08 - Speaker 0\nAnd what we're working on is, providing ways to take your original content, make it more digestible, and distributable across different channels. We are looking at ways to optimize your tone analysis as well as tools to help you detect if AI is being used in your content. So all of that is coming to life in 2024 on Contelly. Okay. It looks like we have one more question, and please drop in any more questions now if you have any.\n\n29:42 - Speaker 0\nBut it looks like, we're the question is, my legal team needs to review every piece of content and won't log in to additional tools. Yes. This is not a unique problem. We've heard this from many of our customers. So we do have a tool called the off platform review.\n\n29:59 - Speaker 0\nAnd essentially within the workflow, once you meet that step, we will trigger an email to your your legal team so they can open that up and review the content there. So it's a great way to help them, achieve the goal they have of reviewing the content and keeping everything centralized within the Contently platform. Alright. I think that is all the questions we have. I wanna thank you all again for your time today.\n\n30:27 - Speaker 0\nI know your time is valuable, and I'm glad you chose to spend it with us. Hopefully, we'll hear from you soon. Thank you.\n\n```\n\n### Response: 200\n```json\n# ProductMind P2 Spec\n\n\n## Background\n\n- There is a lot of raw data, structured and unstructured, about a product or company that ESW acquires. This includes things like files, financials, product videos, log files, support tickets, etc.\n\t- This data serves several functions in the company, including engineering, technical product management, commercial product management, sales, support, finance, and executive management, e.g.\n\t\t- SME interviews, product demos\n\t\t- Sales/Marketing materials - presentations, PDFs\n\t\t- Code & architectural design information\n\t\t- Sales documents - contracts, invoices\n\t\t- A lot of data is secluded in 3rd party systems - helpdesk software, CRMs, ERPs, accounting etc\n\t- This content comes in all sorts of shapes and sizes: text (lots of input formats) but also richer media (images, graphs, charts, tables, videos)\n\n## Problem statement\n\n- We need a way to consistently get to the right information, both so humans can find the information and also to help the entire organization adopt AI by enabling people to build assistants that benefit from the enhanced RAG.\n\n## Solution \n\n\n### Approach\n\n- Structure the data in a hierarchy by its quality, with raw data from the target at the bottom of the pyramid, summaries/insights in the middle, and polished work units (e.g., Stickiness Evaluation) at the top, enabling open exploration of data by leveraging all the layers.\n\t- Level 1 is the raw data. Ingested data is used with an LLM so someone can ask questions about the data and get good answers. Putting it all into a RAG is a baseline approach, but it may not be the best.\n\t- Upper levels contain more value. These are condensed insights/summaries thoughtfully created from the raw data and injected back into the knowledge base, such as auto-generated context packs, stickiness reports, and key feature extracts.\n- The bottom layers should leverage 3rd party no-code solutions as much as possible to avoid duplicate effort and the \"steamroller effect\". The top layers represent more durable IP in things like second brains.\n- We want standard patterns and architecture to apply across different products/teams at ESW to gain leverage and scale, rather than each team building its own siloed solutions.\n- Second Brains represent the most valuable IP - the unique insights on what information is most important to extract and represent.\n\n### Data & Schema\n\n- L1: Raw content (documents, code, videos) is imported from the A&I data room or 3rd party apps into a product knowledge space and indexed\n\t- Content is tagged manually (function, type, status, date) to improve retrieval\n\t- Documents are pre-processed/enriched for use with AI when needed (ITD #3)\n- L2: Context Packs capture specific, typed product information (e.g. product features, data model, commercial model), that serves as a base in creating work units\n\t- Content is created through GenAI flows based on raw data and indexed/tagged for reuse (e.g. creating the feature pack from product videos using Gemini)\n\t- Context packs include Thoughts (include CQs, Doubts, Assumptions, and Unusual Facts). These are then used as a basis for AI-led customer interviews aimed at clarifying/confirming the thoughts\n- L3: Work Units are complex deliverables created based on L1 and L2 information\n\t- Content is created through GenAI-enabled tools (e.g. the spec writer in TPM or stickiness unit in CPM) and indexed/tagged for reuse\n\n[link_preview](https://lucid.app/lucidchart/53adf0ab-6bd9-45b8-a57d-810ae0c02c63/edit?beaconFlowId=AE07B432EF9307BA&invitationId=inv_ebe8222b-45de-410c-9d55-59521ce43a59&page=0_0#)\n\n\n## ITDs\n\n1. **Structure data into three layers: L1 raw data from the acquired company, L2 refined&highly reusable data, L3 work-units**\n\t- L2 product data/documents that are commonly reused across work units (e.g., feature lists and pain/features/benefits of a product used in CPM&TPM, etc). This concept does not exist today in ESW, but having these stand-alone, reusable data items avoids duplicate efforts and improves quality\n\t- L3 work unit documents - are different from L2 data in purpose; if L2 data is designed to capture a specific type of information (Stickiness Analysis, AI Roadmap, S2) and be reusable, L3 (WUs) are designed to answer an important business question or drive decisions.\n2. **Use AWS serverless solutions as the main stack for semantic search/retrieval.** Although this is a fast-evolving space, it will become commoditized much faster than database hosting did, and AWS is already keeping up with the latest developments (e.g., [hybrid search](https://aws.amazon.com/blogs/machine-learning/amazon-bedrock-knowledge-bases-now-supports-hybrid-search/), i.e., combining semantic + text search).\n\t- **Use AWS Bedrock** [**Knowledge Bases** ](https://aws.amazon.com/bedrock/knowledge-bases/)**as the main retrieval engine.**\n\t\t- Note: We would have preferred to use **Amazon Q Business** because it has a [<u>long list of connectors</u>](https://docs.aws.amazon.com/amazonq/latest/qbusiness-ug/connectors-list.html) (including Google Docs, Google Sheets, GitHub, Confluence, Zendesk, Jira, Salesforce, SQL, etc), but this was not chosen because Q Business cannot be used just for Retrieval (it only supports Retrieval + Generation), and it’s [Generation quality is poor](https://docs.google.com/spreadsheets/d/1kdlvaXVFM6-Q6O-wufAtvTNKfq8pJIHpGfoXZpGzYC0/edit?gid=0#gid=0) and we have no control over what model is used under the hood (after several rounds of feedback with the AWS team, we were admitted to that it’s using Sonnet 3.0 for responses, but even after upgrading to 3.5 it’s not clear that it uses that in all cases; additionally, AWS confirmed that they would likely be never be using the most expensive frontier model, which goes against our goals)\n\t- **Use S3 to store & label converted data** - it is well integrated with Amazon Bedrock, Q Business, and common low-code tools (eg. Stack-ai, Flowise)\n3. **Improve retrieval by extracting/converting rich data to AI-friendly text-based formats, e.g.**\n\t- Rich PDFs (with graphs, charts, and tables) can be converted to Markdown (e.g. [<u>PDF to Text AI Converter</u>](https://www.notion.so/trilogy-enterprises/PDF-to-Text-AI-Converter-0ce5d008cb9e49be9911e9e60a808c7e))\n\t- Call transcripts are cleaned up by removing timestamps, reducing the input token count by 20-25%\n\t- Note: we acknowledge this function is in the path of the steamroller, but it is not being done today well by AWS solution for our use cases, and we need a stop-gap until this gets solved.\n- **Improve retrieval by annotating data with rich attributes** - improves data retrieval quality as the retrievers can defined to look up the best type of data and fall back if none is found (e.g. lookup L3 TPM TT and default to L2 C3 model, or L1 raw data)\n\t- These attributes are:\n\t\t- level (L1/2/3)\n\t\t- function (eng, tpm, etc..)\n\t\t- type (feature, architecture, stickiness)\n\t\t- status (draft, SME-reviewed, deprecated)\n\t- Important: **Build generic/reusable AI-enabled tools that produce higher-level data, using reusable 2nd Brains and Schemas**\n\t\t- e.g. an L3 PreLOI & DD specs will use L2 data (eg. architecture, requirements, features) or L1 data (interviews)\n\t\t- e.g., a generic [<u>M&A Chatbot</u>](https://www.notion.so/trilogy-enterprises/M-A-Bot-Prompt-4f945912a61741f78728302f31e68176), that leverages the [<u>Stickiness 2nd Brain</u>](https://www.notion.so/trilogy-enterprises/Product-Stickiness-Evaluation-SB-0313d2da0d704cbe899065d3dfc2529b) and the [<u>Stickiness Report Schema</u>](https://www.notion.so/trilogy-enterprises/Stickiness-Report-Schema-045d50deecbb4c4bbb61ab6a8a8ec745)\n- **Manage 2nd Brains, Schemas, and Context Packs in a centralized repository.** We choose **Notion** because\n\t1. It forces one to stick to the content and avoid wacky formatting with a bunch of complex tables and diagram images that the AI doesn't understand, as we do for example in [DD P2s](https://docs.google.com/document/d/12Zvw8CbLZfafnpvanlVa6X8q3p3ga1fAnpWnXlhUyFA/edit) and [Stickiness WUs](https://docs.google.com/document/d/1LNf44mk7cgd8AqJ4EZNd6GsoAs-Pu1idn_ClwF9UMOU/edit#heading=h.xhf94ciqnjye)\n\t2. There is a clear document hierarchy, and seeing all documents in a tree structure on the left nav bar at all times, including subpages as mandatory links in a page, pushes one to keep things organized and the docs up to date.\n\t3. Additionally, Notion supports synced content sections (e.g., a prompt that includes the SB by reference).\n\n## Architecture Diagram\n\n\n[link_preview](https://lucid.app/lucidchart/e25a69bd-ca86-45b1-b904-e26f0bd0df73/edit?beaconFlowId=388D58709EEDDE42&invitationId=inv_9fb72867-a594-439e-a459-61697833e4e8&page=VP1jSL3THxgx#)\n\n\n\n\n```\n\n\n⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃\n\n## End-point: Convert PDF to Markdown\nThis endpoint converts PDF files to Markdown format. It allows users to provide a URL to a PDF file stored in Google Drive, which the service will then download, process, and convert to Markdown. The converted Markdown is returned by the endpoint and is cached in an S3 bucket for speeding up future access.\n\n### Parameters:\n\n- `url` (string, required): The URL of the PDF file stored in Google Drive to be converted.\n    \n- `provider` (string, optional): The AI provider to use for processing the PDF content. Options are \"claude\" (default) or \"openai\".\n    \n\nAll parameters should be passed in the request body as JSON.\n\n> **Note:** The Google Drive file must be shared with the `cpm-diligence@trilogy.com` group for this endpoint to access and process it.\n### Method: POST\n>```\n>https://productmind.trilogy.com/convert/pdf\n>```\n### Body (**raw**)\n\n```json\n{\n  \"url\": \"https://drive.google.com/file/d/1ljWPbWQImvfoY3V5ruBMoahh1nBdCBKr/view\"\n}\n```\n\n### Response: 200\n```json\n# Page 1\n\n# Act-On Executive Summary\n\n![act-on logo](act-on-logo.png)\n\n# Page 2\n\n# The Modern Platform Fueling MarTech 3.0\n\n## Daily Clicks\nShows the clicks per day of selected timeframe.\n\n...\n```\n\n\n⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃\n\n## End-point: Convert Google Doc / Word to Markdown\nThis endpoint converts Google Docs to Markdown format. It allows users to provide a URL to a Google Doc, which the service will then download, process, and convert to Markdown. The converted Markdown is returned by the endpoint and is cached in an S3 bucket for speeding up future access.\n\n### Parameters:\n- `url` (string, required): The URL of the Google Doc to be converted.\n\nAll parameters should be passed in the request body as JSON.\n\n> **Note:** The Google Drive file must be shared with the `cpm-diligence@trilogy.com` group for this endpoint to access and process it.\n### Method: POST\n>```\n>https://productmind.trilogy.com/convert/gdoc\n>```\n### Body (**raw**)\n\n```json\n{\n  \"url\": \"https://docs.google.com/document/d/1-CJEZNzjNq6i_JHA9_9R-8Jrm5FEfzyRFQP_v2esAdY/edit?usp=drive_link\"\n}\n\n```\n\n### Response: 200\n```json\n# Sample Google Doc\n\nThis is the converted content of the Google Doc.\n\n## Section 1\n\nContent of section 1\n\n## Section 2\n\nContent of section 2...`\n```\n\n\n⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃\n\n## End-point: Convert Google Sheet / Excel to Markdown\nThis endpoint converts Google Sheets to Markdown format. It allows users to provide a URL to a Google Sheet, which the service will then download, process, and convert to Markdown. The converted Markdown is returned by the endpoint and is cached in an S3 bucket for speeding up future access.\n\n### Parameters:\n- `url` (string, required): The URL of the Google Sheet to be converted.\n\nAll parameters should be passed in the request body as JSON.\n\n> **Note:** The Google Drive file must be shared with the `cpm-diligence@trilogy.com` group for this endpoint to access and process it.\n### Method: POST\n>```\n>https://productmind.trilogy.com/convert/gsheet\n>```\n### Body (**raw**)\n\n```json\n{\n  \"url\": \"https://docs.google.com/spreadsheets/d/1WF2KHMPulpin70CA1o6vH2-ZAhKrsm92/edit?usp=drive_link&ouid=107958425101123608031&rtpof=true&sd=true\"\n}\n\n```\n\n### Response: 200\n```json\n# Sample Google Sheet\n\n| Column 1 | Column 2 | Column 3 |\n|----------|----------|----------|\n| Value 1  | Value 2  | Value 3  |\n| Value 4  | Value 5  | Value 6  |\n\n## Sheet 2\n\n| Column A | Column B |\n|----------|----------|\n| Value A  | Value B  |\n| Value C  | Value D  |`\n| Value E  | Value F  |`\n```\n\n\n⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃\n\n## End-point: Convert Notion Page to Markdown\nThis endpoint converts Notion pages to Markdown format. It allows users to provide a URL to a Notion page, which the service will then process and convert to Markdown. The converted Markdown is returned by the endpoint and is cached in an S3 bucket for speeding up future access.\n\n### Parameters:\n\n- `url` (string, required): The URL of the Notion page to be converted.\n    \n- `export_child_pages` (boolean, optional): Whether to include child pages in the conversion. Default is false.\n    \n\nAll parameters should be passed in the request body as JSON.\n\n> **Note:** The Notion page must be shared with the ProductMind-Export-Import integration for this endpoint to access and process it.  \nTo share the page with the exporter, follow these steps:  \n1\\. Open the page in Notion.  \n2\\. Open the 'three dots' menu in the top-right corner.  \n3\\. Ensure that 'ProductMind-Export-Import' is listed under 'Connections'. If not, add it.\n### Method: POST\n>```\n>https://productmind.trilogy.com/convert/notion\n>```\n### Body (**raw**)\n\n```json\n{\n  \"url\": \"https://www.notion.so/trilogy-enterprises/test_bogdan-md-35469c94e208495d93fb4510daa816f0\",\n  \"export_child_pages\": true\n}\n\n```\n\n### Response: 200\n```json\n# Sample Notion Page\n\nThis is the converted content of the Notion page.\n\n## Child Page 1\n\nContent of child page 1...\n\n## Child Page 2\n\nContent of child page 2...\n```\n\n\n⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃\n\n## End-point: Convert Postman Collection to Markdown\nThis endpoint converts Postman collections to Markdown format. It allows users to provide a URL to a Postman collection or folder, which the service will then download, process, and convert to Markdown. The converted Markdown is returned by the endpoint and is cached in an S3 bucket for speeding up future access.\n\n### Parameters:\n\n- `url` (string, required): The URL of the Postman collection or folder to be converted.\n    \n\nAll parameters should be passed in the request body as JSON.\n\n> **Note:** The following URL formats are supported for Postman collections:  \n\\- Workspace folder: `https://ws-eng.postman.co/workspace/Platform-Prod~66ec436e-5fcd-43ad-964c-f70d5ca1225f/folder/31124709-c9060ee9-6b7c-4d32-861c-7ff22d5d9c60`  \n\\- Collection: `https://ws-eng.postman.co/workspace/ProductMind~4f2b8040-ee72-4afe-92d0-b189c4dac3e9/collection/38070356-941aecfa-a192-46a6-98b0-756a76a4693f?action=share&creator=38070356`  \n\\- Workspace folder (alternative format): `https://ws-eng.postman.co/workspace/ProductMind~4f2b8040-ee72-4afe-92d0-b189c4dac3e9/folder/38070356-b86b8070-d4d8-44b4-9361-c47d3e2256b2?action=share&source=copy-link&creator=38070356&ctx=documentation`  \n\\- Collection (alternative format): `https://ws-eng.postman.co/workspace/Platform-Prod~66ec436e-5fcd-43ad-964c-f70d5ca1225f/collection/31124709-d038145a-a2fd-46f9-8cd1-f6024afbbf72   `\\- Workspace folder (without workspace name): `https://ws-eng.postman.co/workspace/4f2b8040-ee72-4afe-92d0-b189c4dac3e9/folder/38070356-5f19b4dd-c3e9-48cd-9383-7d4d030f74ed?action=share&source=copy-link&creator=38070356&ctx=documentation`\n### Method: POST\n>```\n>https://productmind.trilogy.com/convert/postman\n>```\n### Body (**raw**)\n\n```json\n{\n  \"url\": \"https://ws-eng.postman.co/workspace/ProductMind~4f2b8040-ee72-4afe-92d0-b189c4dac3e9/collection/38070356-941aecfa-a192-46a6-98b0-756a76a4693f?action=share&creator=38070356\"\n}\n\n```\n\n### Response: 200\n```json\n# Sample Postman Collection\n\n## Endpoint 1: GET /api/resource\n\nDescription of endpoint 1..\n\n### Request\n\n\\`\\`\\`http\nGET /api/resource HTTP/1.1\nHost: api.example.com\n\\`\\`\\`\n\n### Response\n\n\\`\\`\\`json\n{\n  \"key\": \"value\"\n}\n\\`\\`\\`\n\n## Endpoint 2: POST /api/resource\n\nDescription of endpoint 2...\n\n### Request\n\n\\`\\`\\`http\nPOST /api/resource HTTP/1.1\nHost: api.example.com\nContent-Type: application/json\n\n{\n  \"data\": \"example\"\n}\n\\`\\`\\`\n\n### Response\n\n\\`\\`\\`json\n{\n  \"id\": \"123\",\n  \"status\": \"created\"\n}\n\\`\\`\\``\n```\n\n\n⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃\n\n## End-point: Convert Video to Transcript\nThis endpoint converts mp4 videos to their transcript in plain text. It allows users to provide a URL to a video on Google Drive, which the service will then download and transcribe. The converted transcription is returned by the endpoint and is cached in an S3 bucket for speeding up future access.\n\nIf there is a transcript already next to the video file on Google Drive then that file will be used instead of generating a new one. See note below about permissions.\n\n### Transcript file naming convention\n\nThe following transcript naming conventions are recognized:\n\n1. file with the same name with .txt or .docx extension\n    \n2. Google Meet recording naming format, e.g\n    \n    1. Waleed Bin Inam Satti and Bogdan Tenea – 2024/09/09 13:34 EEST – Transcript\n        \n    2. Waleed Bin Inam Satti and Bogdan Tenea – 2024/09/09 13:34 EEST – Recording\n        \n3. [read.ai](http://read.ai/) recording naming format, e.g.\n    \n    1. Project Passage _ Product Demo (Trilogy) Recording.mp4\n        \n    2. Project Passage _ Product Demo (Trilogy) Transcript.txt\n        \n\nWe support txt, docx and google doc formats for the transcripts, they all will be converted to plain text (.txt).\n\n### Parameters:\n\n- `url` (string, required): The URL of the Postman collection or folder to be converted.\n    \n- `provider` (string, optional, default: `deepgram`): One of the supported providers that can be used for transcribing:\n    \n    - `aws` - using Amazon Transcribe\n        \n    - `deepgram` (default) - using Deepgram\n        \n    - `google` - using Google Speech (chirp 2 model) - note that this option doesn't support speaker recognition and timestamps\n        \n- `force_reprocess` (boolean, optional, default: `false`): Reprocess the video even if the results are already cached. You shouldn't normally use this, but can be helpful when evaluating different providers for the same file.\n    \n\n### Note on permissions\n\n- In order to check and find a transcript file in Google drive next to the video the `cpm-diligence@trilogy.com` service account needs to have view access to the folder containing the video and transcript (otherwise we can't check whether there is another file next to the video)\n    \n- In order to transcribe a video the `cpm-diligence@trilogy.com` service account needs to have access to it, and the video needs to allow viewers to download the video (you can change this on the share dialog under the settings clicking the cog icon). This is sometimes for meeting recordings off by default.\n### Method: POST\n>```\n>https://productmind.trilogy.com/convert/video\n>```\n### Body (**raw**)\n\n```json\n{\n  \"url\": \"https://drive.google.com/file/d/1P_E5F2dDisTr7vG-x-g-PuLVGB4BJW9D/view?usp=drive_link\"\n}\n\n```\n\n### Response: 200\n```json\n00:01 - Speaker 0\nThis is a sample video that we can use I integration tests to test video transcriptions to text and it doesn't serve any other purpose. This is the Google Drive folder with the integration files. This is where it will get added.\n\n```\n\n\n⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃\n# 📁 Collection: Extract \n\n\n## End-point: Extract entities from video from summary checklist\nEXPERIMENTAL\n\nAllows extracting entities from video based on only a summary checklist that includes the topic and a checklist.\n\nThe processing first proposes an entity schema (using prompts given in `schema_generation_prompts_notion_page` parameter) and then invokes the Video processing with this schema. The generated schema is added as a child page under this Notion page (it can be useful for review): [https://www.notion.so/trilogy-enterprises/Generated-prompt-packs-12185e927d3180a7b9c5dce8bc1e0506](https://www.notion.so/trilogy-enterprises/Generated-prompt-packs-12185e927d3180a7b9c5dce8bc1e0506)\n\n_Note that the execution can timeout especially with longer videos. However the processing will still finish in the background, in such cases you will receive the results in email. (If you don't get the results within 30 minutes please reach out to ProductMind team on_ [https://chat.google.com/room/AAAAvVGoSag?cls=7](https://chat.google.com/room/AAAAvVGoSag?cls=7))\n\n## Parameters\n\n- `video` (string, required): The Google Drive URL of the video to be processed.\n    \n- `topic` (string, required): Topic of the evaluation\n    \n- `checklist` (string, required): Key expectations to get out from the video (can be markdown formatted)\n    \n- `notification_receiver_emails` (array of strings, required): List of email addresses where the result emails will be sent by the Video processing.\n    \n- `product_name` (string, required): Name of the product evaluated - currently only used in prompts, in future could be used for KB queries\n    \n- `product_context` (string, optional): Additional context in markdown format passed to extraction\n    \n- `schema_generation_prompts_notion_page` (string, optional): The root page of a Notion page that contains the generic base prompts that are used to generate the proper prompts for this run. You can safely leave this empty. **Default**: [https://www.notion.so/trilogy-enterprises/Base-Prompts-12185e927d3180a0b4bad07763079a25](https://www.notion.so/trilogy-enterprises/Base-Prompts-12185e927d3180a0b4bad07763079a25)\n    \n- `video_conversion_prompts_notion_page` (string, optional): When specified the whole prompt inferring process will be skipped and the video processing will be called with the referenced root Notion page prompts. Only specify this if you explicitly want to skip the inferring, most likely because you are iterating on a previous processing and tweaked the previously generated prompts just slighty. **Default**: `null`.\n    \n- `llm` (string, optional): The LLM to use for inferring the entity schema. Supported options:\n    \n    - `openai` (**default**): to use o1-preview\n        \n    - `claude` to use Claude 3.5 Sonnet\n        \n    - `google` to use Gemini 1.5 pro\n        \n- `only_prompts_generation` (boolean, optional): When set to `true` only the prompt generation process will be executed, it will skip the second step of calling the Video processing blackbox. Useful when trying different input prompts or different LLMs for the schema generation. **Default**: `false`.\n    \n\n## Results\n\nResults will be emailed to the given notification addresses, they will **not** be returned by the endpoint.\n### Method: POST\n>```\n>https://pr93.productmind.trilogy.com/extract/video/from_checklist\n>```\n### Body (**raw**)\n\n```json\n{\n  \"video\": \"https://drive.google.com/file/d/10sjjL6YOAeIrpDTA-TvBybwCiM1MBclT/view\",\n  \"topic\": \"Customer Pain Points\",\n  \"checklist\": \" Extract pains, and related features and benefits for Contently\",\n  \"product_name\": \"Contently\",\n  \"product_context\": null,\n  \"schema_generation_prompts_notion_page\": \"https://www.notion.so/trilogy-enterprises/Prompts-12185e927d3180a0b4bad07763079a25\",\n  \"notification_receiver_emails\": [\"akos.orban@trilogy.com\"],\n  \"llm\": \"openai\"\n}\n```\n\n\n⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃\n\n## End-point: Extract entities from video with structured schema\nAllows extracting entities from video based on a pre-defined structured schema for the given entities.\n\nSame functionality as available behind this form: [https://doc-gen.ti.trilogy.com/](https://doc-gen.ti.trilogy.com/)\n\n_Note that this endpoint requires a Bearer auth token to be specifed._\n\n## Parameters\n\n- `file_inputs` (array of objects, required): Inputs to process\n    \n    - `file_link` (string, required): The Google Drive URL of the video\n        \n    - `start_offset` (integer, optional): Start offset from where to process the video\n        \n    - `end_offset` (integer, optional): End offset until where to process the video\n        \n- `notification_receiver_emails` (array of strings, required): List of email addresses where the result emails will be sent by the Video processing.\n    \n- `product_name` (string, required): Name of the product evaluated - currently only used in prompts, in future could be used for KB queries\n    \n- `product_context` (string, optional): Additional context in markdown format passed to extraction\n    \n- `notion_prompts_root` (string, required): When specified the whole prompt inferring process will be skipped and the video processing will be called with the referenced root Notion page prompts. Only specify this if you explicitly want to skip the inferring, most likely because you are iterating on a previous processing and tweaked the previously generated prompts just slighty. **Default**: `null`.\n    \n\n## Results\n\nResults will be emailed to the given notification addresses. The response will include the ARN of a state-machine execution where progress could be monitored.\n### Method: POST\n>```\n>https://pr93.productmind.trilogy.com/extract/video/from_schema\n>```\n### Body (**raw**)\n\n```json\n{\n  \"file_inputs\": [{ \"file_link\": \"https://drive.google.com/file/d/10sjjL6YOAeIrpDTA-TvBybwCiM1MBclT/view\", \"start_offset\": null, \"end_offset\": null }],\n  \"product_name\": \"Contently\",\n  \"product_context\": null,\n  \"notion_prompts_root\": \"https://www.notion.so/trilogy-enterprises/Pains-Features-Benefits-Doc-Gen-Prompts-9397b02357b5475c90a46d45c8a08f4c\",\n  \"notification_receiver_emails\": [\"akos.orban@trilogy.com\"]\n}\n```\n\n### 🔑 Authentication bearer\n\n|Param|value|Type|\n|---|---|---|\n|token||string|\n\n\n\n⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃\n\n## End-point: Extract details from contracts (experimental)\nEXPERIMENTAL\n\nAllows extracting details from contracts\n\n## Parameters\n\n- `company` (string, required): Name of the Company of which contracts are processed\n    \n- `source` (object, optional): Google Sheet source for the contracts to process\n    \n    - `url` (string, required): URL of the Google Sheet\n        \n    - `sheet_name` (string, optional): Name of the sheet to use. If not specified will use the first one.\n        \n    - `document_column_name` (string, required): Name of the column containing the Google Drive URL to the PDF of the contract\n        \n    - `limit` (int, optional): Number of contracts to process. **Default**: no limit\n        \n    - `offset` (int, optional): From which contract to start processing. **Default**: 0\n        \n- `contracts` (array of strings, optional): The list of contracts to process, each entry should be the url of a Google Drive PDF contract\n    \n- `notification_receiver_emails` (array of strings, optional): A list of email addresses to which a notification will be sent after processing finishes.\n    \n- `prompts` (object, optional): Notion page URLs pointing to prompts that are used in various steps in the process. Any or all defaults can be overridden, it's enough to include the ones that need to be overriden in the inputs. For example: `{ \"terms_a\": \"http://mynotion.page\"}` will result in using the custom prompt for the \"Terms A\" extraction, while all of the result will use the defaults.\n    \n    - `terms_a`: Notion page url for 1st part of terms extraction. Default: [https://www.notion.so/trilogy-enterprises/Contract-analysis-prompt-Step-1-General-terms-A-14285e927d3180f792fcdc0db7f0bbdf](https://www.notion.so/trilogy-enterprises/Contract-analysis-prompt-Step-1-General-terms-A-14285e927d3180f792fcdc0db7f0bbdf)\n        \n    - `terms_b`: Notion page url for 2nd part of terms extraction. Default: [https://www.notion.so/trilogy-enterprises/Contract-analysis-prompt-Step-1-General-terms-B-14285e927d3180bb8e12c33917d4eb74](https://www.notion.so/trilogy-enterprises/Contract-analysis-prompt-Step-1-General-terms-B-14285e927d3180bb8e12c33917d4eb74)\n        \n    - `entitlements`: Notion page url for Entitlement terms extraction. Default: [https://www.notion.so/trilogy-enterprises/Contract-analysis-prompt-Step-2-Entitlements-14285e927d3180f0b608c33bd970775f](https://www.notion.so/trilogy-enterprises/Contract-analysis-prompt-Step-2-Entitlements-14285e927d3180f0b608c33bd970775f)\n        \n    - `response_schema`: Notion page url with the JSON schema for terms and entitlements extraction. Default: [https://www.notion.so/trilogy-enterprises/Response-schema-14385e927d318047989ff78a83264594](https://www.notion.so/trilogy-enterprises/Response-schema-14385e927d318047989ff78a83264594)\n        \n    - `reconciliation_root`: A Notion parent page url that includes underneath the 3 prompts (\"Reconciliation - term subject prompt\", \"Reconciliation - term standard prompt\", \"Reconciliation - term type prompt\") used for reconciliation. Default: [https://www.notion.so/trilogy-enterprises/Prompts-12e85e927d31801fb40af168a4f58496](https://www.notion.so/trilogy-enterprises/Prompts-12e85e927d31801fb40af168a4f58496)\n        \n- `skip_reconciliation` (boolean, optional): Controls whether to skip the reclassification of the term type (potential switch between Standard and Non-Standard) after processing all batches. By default the reconciliation is on, but it could result in outgrowing the context window, in such case you can set it to `true` to skip this processing step. **Default**: `false`\n    \n- `skip_cache` (boolean, optional): Controls whether to skip cached term extractions. Term extractions are cached in batches, if anything in the batch changes (contracts content, batch size, prompt on Notion) then it will automatically skip the cache and regenerate. Only use this option if you explicilty want to retry extraction without any other changes. **Default**: `false`\n    \n\nNote that either `source` or `contracts` is required.\n\n## Results\n\nThe processing can take quite long (depending on the number of contracts this can be around an hour or even longer) and it will happen in the background. The only thing returned is a step function execution ARN where the processing can be tracked.\n\nOnce processing finishes an email will be sent to the addresses given in `notification_receiver_emails` together with a donwload link for the results.\n### Method: POST\n>```\n>https://pr127.productmind.trilogy.com/extract/contracts\n>```\n### Body (**raw**)\n\n```json\n{\n  \"company\": \"cloudsense\",\n  \"contracts\": [\n     \"https://drive.google.com/file/d/16eVHNAwqgB4J45yKp2SvxwuzhuSFPAXV/view?usp=drive_link\",\n     \"https://drive.google.com/file/d/19daKao-zMeGu0sQdJqABvLfCCtWQVX51/view?usp=drive_link\",\n     \"https://drive.google.com/file/d/1paUCPTGUHl7o6tXnaA40GBmaaGf8z1MU/view?usp=drive_link\"\n  ],\n  \"notification_receiver_emails\": [\"akos.orban@trilogy.com\"]\n}\n```\n\n### Response: undefined\n```json\n{\n    \"message\": \"Contract analysis started\",\n    \"execution_arn\": \"arn:aws:states:us-east-1:992382370892:execution:q-productmind-backend-pr127-contractAnalysis:d5f75fa3-d0e7-44bb-91ba-4fa89f6a817f\"\n}\n```\n\n### Response: undefined\n```json\n{\n    \"message\": \"Contract analysis started\",\n    \"execution_arn\": \"arn:aws:states:us-east-1:992382370892:execution:q-productmind-backend-pr127-contractAnalysis:d5f75fa3-d0e7-44bb-91ba-4fa89f6a817f\"\n}\n```\n\n\n⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃\n"},{"id":"67d05a42-dbee-4512-93a6-7149d238f818","name":"Convert Postman folder to Markdown","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"url\": \"https://ws-eng.postman.co/workspace/ProductMind~4f2b8040-ee72-4afe-92d0-b189c4dac3e9/folder/38070356-aa3a7499-2b08-4211-ae00-001c4931042b?action=share&creator=38070356&ctx=documentation\"\n}","options":{"raw":{"language":"json"}}},"url":"https://pr131.productmind.trilogy.com/convert/url"},"status":"OK","code":200,"_postman_previewlanguage":"plain","header":[{"key":"Date","value":"Fri, 22 Nov 2024 17:50:20 GMT"},{"key":"Content-Type","value":"text/markdown; charset=utf-8"},{"key":"Content-Length","value":"12340"},{"key":"Connection","value":"keep-alive"},{"key":"x-amzn-RequestId","value":"3a84bc01-0c22-46a9-8ec5-586eed9dde88"},{"key":"x-amz-apigw-id","value":"BqOeLFMsoAMEchg="},{"key":"X-Amzn-Trace-Id","value":"Root=1-6740c45a-3f57b5ba6ab92f826656043d;Sampled=1;Lineage=1:59f458cb:0"}],"cookie":[],"responseTime":null,"body":"# Project: ProductMind - API\nThis folder contains endpoints for **extracting entities from videos to Markdown format**.\n# 📁 Collection: Extract \n\n\n## End-point: Extract entities from video from summary checklist\nEXPERIMENTAL\n\nAllows extracting entities from video based on only a summary checklist that includes the topic and a checklist.\n\nThe processing first proposes an entity schema (using prompts given in `schema_generation_prompts_notion_page` parameter) and then invokes the Video processing with this schema. The generated schema is added as a child page under this Notion page (it can be useful for review): [https://www.notion.so/trilogy-enterprises/Generated-prompt-packs-12185e927d3180a7b9c5dce8bc1e0506](https://www.notion.so/trilogy-enterprises/Generated-prompt-packs-12185e927d3180a7b9c5dce8bc1e0506)\n\n_Note that the execution can timeout especially with longer videos. However the processing will still finish in the background, in such cases you will receive the results in email. (If you don't get the results within 30 minutes please reach out to ProductMind team on_ [https://chat.google.com/room/AAAAvVGoSag?cls=7](https://chat.google.com/room/AAAAvVGoSag?cls=7))\n\n## Parameters\n\n- `video` (string, required): The Google Drive URL of the video to be processed.\n    \n- `topic` (string, required): Topic of the evaluation\n    \n- `checklist` (string, required): Key expectations to get out from the video (can be markdown formatted)\n    \n- `notification_receiver_emails` (array of strings, required): List of email addresses where the result emails will be sent by the Video processing.\n    \n- `product_name` (string, required): Name of the product evaluated - currently only used in prompts, in future could be used for KB queries\n    \n- `product_context` (string, optional): Additional context in markdown format passed to extraction\n    \n- `schema_generation_prompts_notion_page` (string, optional): The root page of a Notion page that contains the generic base prompts that are used to generate the proper prompts for this run. You can safely leave this empty. **Default**: [https://www.notion.so/trilogy-enterprises/Base-Prompts-12185e927d3180a0b4bad07763079a25](https://www.notion.so/trilogy-enterprises/Base-Prompts-12185e927d3180a0b4bad07763079a25)\n    \n- `video_conversion_prompts_notion_page` (string, optional): When specified the whole prompt inferring process will be skipped and the video processing will be called with the referenced root Notion page prompts. Only specify this if you explicitly want to skip the inferring, most likely because you are iterating on a previous processing and tweaked the previously generated prompts just slighty. **Default**: `null`.\n    \n- `llm` (string, optional): The LLM to use for inferring the entity schema. Supported options:\n    \n    - `openai` (**default**): to use o1-preview\n        \n    - `claude` to use Claude 3.5 Sonnet\n        \n    - `google` to use Gemini 1.5 pro\n        \n- `only_prompts_generation` (boolean, optional): When set to `true` only the prompt generation process will be executed, it will skip the second step of calling the Video processing blackbox. Useful when trying different input prompts or different LLMs for the schema generation. **Default**: `false`.\n    \n\n## Results\n\nResults will be emailed to the given notification addresses, they will **not** be returned by the endpoint.\n### Method: POST\n>```\n>https://pr93.productmind.trilogy.com/extract/video/from_checklist\n>```\n### Body (**raw**)\n\n```json\n{\n  \"video\": \"https://drive.google.com/file/d/10sjjL6YOAeIrpDTA-TvBybwCiM1MBclT/view\",\n  \"topic\": \"Customer Pain Points\",\n  \"checklist\": \" Extract pains, and related features and benefits for Contently\",\n  \"product_name\": \"Contently\",\n  \"product_context\": null,\n  \"schema_generation_prompts_notion_page\": \"https://www.notion.so/trilogy-enterprises/Prompts-12185e927d3180a0b4bad07763079a25\",\n  \"notification_receiver_emails\": [\"akos.orban@trilogy.com\"],\n  \"llm\": \"openai\"\n}\n```\n\n\n⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃\n\n## End-point: Extract entities from video with structured schema\nAllows extracting entities from video based on a pre-defined structured schema for the given entities.\n\nSame functionality as available behind this form: [https://doc-gen.ti.trilogy.com/](https://doc-gen.ti.trilogy.com/)\n\n_Note that this endpoint requires a Bearer auth token to be specifed._\n\n## Parameters\n\n- `file_inputs` (array of objects, required): Inputs to process\n    \n    - `file_link` (string, required): The Google Drive URL of the video\n        \n    - `start_offset` (integer, optional): Start offset from where to process the video\n        \n    - `end_offset` (integer, optional): End offset until where to process the video\n        \n- `notification_receiver_emails` (array of strings, required): List of email addresses where the result emails will be sent by the Video processing.\n    \n- `product_name` (string, required): Name of the product evaluated - currently only used in prompts, in future could be used for KB queries\n    \n- `product_context` (string, optional): Additional context in markdown format passed to extraction\n    \n- `notion_prompts_root` (string, required): When specified the whole prompt inferring process will be skipped and the video processing will be called with the referenced root Notion page prompts. Only specify this if you explicitly want to skip the inferring, most likely because you are iterating on a previous processing and tweaked the previously generated prompts just slighty. **Default**: `null`.\n    \n\n## Results\n\nResults will be emailed to the given notification addresses. The response will include the ARN of a state-machine execution where progress could be monitored.\n### Method: POST\n>```\n>https://pr93.productmind.trilogy.com/extract/video/from_schema\n>```\n### Body (**raw**)\n\n```json\n{\n  \"file_inputs\": [{ \"file_link\": \"https://drive.google.com/file/d/10sjjL6YOAeIrpDTA-TvBybwCiM1MBclT/view\", \"start_offset\": null, \"end_offset\": null }],\n  \"product_name\": \"Contently\",\n  \"product_context\": null,\n  \"notion_prompts_root\": \"https://www.notion.so/trilogy-enterprises/Pains-Features-Benefits-Doc-Gen-Prompts-9397b02357b5475c90a46d45c8a08f4c\",\n  \"notification_receiver_emails\": [\"akos.orban@trilogy.com\"]\n}\n```\n\n### 🔑 Authentication bearer\n\n|Param|value|Type|\n|---|---|---|\n|token||string|\n\n\n\n⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃\n\n## End-point: Extract details from contracts (experimental)\nEXPERIMENTAL\n\nAllows extracting details from contracts\n\n## Parameters\n\n- `company` (string, required): Name of the Company of which contracts are processed\n    \n- `source` (object, optional): Google Sheet source for the contracts to process\n    \n    - `url` (string, required): URL of the Google Sheet\n        \n    - `sheet_name` (string, optional): Name of the sheet to use. If not specified will use the first one.\n        \n    - `document_column_name` (string, required): Name of the column containing the Google Drive URL to the PDF of the contract\n        \n    - `limit` (int, optional): Number of contracts to process. **Default**: no limit\n        \n    - `offset` (int, optional): From which contract to start processing. **Default**: 0\n        \n- `contracts` (array of strings, optional): The list of contracts to process, each entry should be the url of a Google Drive PDF contract\n    \n- `notification_receiver_emails` (array of strings, optional): A list of email addresses to which a notification will be sent after processing finishes.\n    \n- `prompts` (object, optional): Notion page URLs pointing to prompts that are used in various steps in the process. Any or all defaults can be overridden, it's enough to include the ones that need to be overriden in the inputs. For example: `{ \"terms_a\": \"http://mynotion.page\"}` will result in using the custom prompt for the \"Terms A\" extraction, while all of the result will use the defaults.\n    \n    - `terms_a`: Notion page url for 1st part of terms extraction. Default: [https://www.notion.so/trilogy-enterprises/Contract-analysis-prompt-Step-1-General-terms-A-14285e927d3180f792fcdc0db7f0bbdf](https://www.notion.so/trilogy-enterprises/Contract-analysis-prompt-Step-1-General-terms-A-14285e927d3180f792fcdc0db7f0bbdf)\n        \n    - `terms_b`: Notion page url for 2nd part of terms extraction. Default: [https://www.notion.so/trilogy-enterprises/Contract-analysis-prompt-Step-1-General-terms-B-14285e927d3180bb8e12c33917d4eb74](https://www.notion.so/trilogy-enterprises/Contract-analysis-prompt-Step-1-General-terms-B-14285e927d3180bb8e12c33917d4eb74)\n        \n    - `entitlements`: Notion page url for Entitlement terms extraction. Default: [https://www.notion.so/trilogy-enterprises/Contract-analysis-prompt-Step-2-Entitlements-14285e927d3180f0b608c33bd970775f](https://www.notion.so/trilogy-enterprises/Contract-analysis-prompt-Step-2-Entitlements-14285e927d3180f0b608c33bd970775f)\n        \n    - `response_schema`: Notion page url with the JSON schema for terms and entitlements extraction. Default: [https://www.notion.so/trilogy-enterprises/Response-schema-14385e927d318047989ff78a83264594](https://www.notion.so/trilogy-enterprises/Response-schema-14385e927d318047989ff78a83264594)\n        \n    - `reconciliation_root`: A Notion parent page url that includes underneath the 3 prompts (\"Reconciliation - term subject prompt\", \"Reconciliation - term standard prompt\", \"Reconciliation - term type prompt\") used for reconciliation. Default: [https://www.notion.so/trilogy-enterprises/Prompts-12e85e927d31801fb40af168a4f58496](https://www.notion.so/trilogy-enterprises/Prompts-12e85e927d31801fb40af168a4f58496)\n        \n- `skip_reconciliation` (boolean, optional): Controls whether to skip the reclassification of the term type (potential switch between Standard and Non-Standard) after processing all batches. By default the reconciliation is on, but it could result in outgrowing the context window, in such case you can set it to `true` to skip this processing step. **Default**: `false`\n    \n- `skip_cache` (boolean, optional): Controls whether to skip cached term extractions. Term extractions are cached in batches, if anything in the batch changes (contracts content, batch size, prompt on Notion) then it will automatically skip the cache and regenerate. Only use this option if you explicilty want to retry extraction without any other changes. **Default**: `false`\n    \n\nNote that either `source` or `contracts` is required.\n\n## Results\n\nThe processing can take quite long (depending on the number of contracts this can be around an hour or even longer) and it will happen in the background. The only thing returned is a step function execution ARN where the processing can be tracked.\n\nOnce processing finishes an email will be sent to the addresses given in `notification_receiver_emails` together with a donwload link for the results.\n### Method: POST\n>```\n>https://pr127.productmind.trilogy.com/extract/contracts\n>```\n### Body (**raw**)\n\n```json\n{\n  \"company\": \"cloudsense\",\n  \"contracts\": [\n     \"https://drive.google.com/file/d/16eVHNAwqgB4J45yKp2SvxwuzhuSFPAXV/view?usp=drive_link\",\n     \"https://drive.google.com/file/d/19daKao-zMeGu0sQdJqABvLfCCtWQVX51/view?usp=drive_link\",\n     \"https://drive.google.com/file/d/1paUCPTGUHl7o6tXnaA40GBmaaGf8z1MU/view?usp=drive_link\"\n  ],\n  \"notification_receiver_emails\": [\"akos.orban@trilogy.com\"]\n}\n```\n\n### Response: undefined\n```json\n{\n    \"message\": \"Contract analysis started\",\n    \"execution_arn\": \"arn:aws:states:us-east-1:992382370892:execution:q-productmind-backend-pr127-contractAnalysis:d5f75fa3-d0e7-44bb-91ba-4fa89f6a817f\"\n}\n```\n\n### Response: undefined\n```json\n{\n    \"message\": \"Contract analysis started\",\n    \"execution_arn\": \"arn:aws:states:us-east-1:992382370892:execution:q-productmind-backend-pr127-contractAnalysis:d5f75fa3-d0e7-44bb-91ba-4fa89f6a817f\"\n}\n```\n\n\n⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃ ⁃\n"},{"id":"667e667c-f572-4aae-a4d9-32c8a784ba55","name":"Convert GitHub YAML to Markdown","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"url\": \"https://github.com/trilogy-group/productmind-integration-tests-input/blob/main/ProductMindAPI.yml\"\n}","options":{"raw":{"language":"json"}}},"url":"https://pr131.productmind.trilogy.com/convert/url"},"status":"OK","code":200,"_postman_previewlanguage":"plain","header":[{"key":"Date","value":"Fri, 22 Nov 2024 17:50:54 GMT"},{"key":"Content-Type","value":"text/markdown; charset=utf-8"},{"key":"Content-Length","value":"7324"},{"key":"Connection","value":"keep-alive"},{"key":"x-amzn-RequestId","value":"bb76e43a-5192-41c7-95a3-62f2fa7088f8"},{"key":"x-amz-apigw-id","value":"BqOjpGNnIAMEcjQ="},{"key":"X-Amzn-Trace-Id","value":"Root=1-6740c47d-6573f3277d0fdbdb55bc3eb3;Sampled=1;Lineage=1:59f458cb:0"}],"cookie":[],"responseTime":null,"body":"openapi: 3.0.0\ninfo:\n  title: ProductMind - API\n  version: 1.0.0\nservers:\n  - url: https://productmind.trilogy.com\ntags:\n  - name: Convert\n  - name: Fetch\n  - name: Write\n  - name: Query\n  - name: Sync\npaths:\n  /convert/pdf:\n    post:\n      tags:\n        - Convert\n      summary: Convert PDF to Markdown\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              example:\n                url: >-\n                  https://drive.google.com/file/d/1ljWPbWQImvfoY3V5ruBMoahh1nBdCBKr/view\n      responses:\n        '200':\n          description: Successful response\n          content:\n            application/json: {}\n  /convert/gdoc:\n    post:\n      tags:\n        - Convert\n      summary: Convert Google Doc / Word to Markdown\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              example:\n                url: >-\n                  https://docs.google.com/document/d/1-CJEZNzjNq6i_JHA9_9R-8Jrm5FEfzyRFQP_v2esAdY/edit?usp=drive_link\n      responses:\n        '200':\n          description: Successful response\n          content:\n            application/json: {}\n  /convert/gsheet:\n    post:\n      tags:\n        - Convert\n      summary: Convert Google Sheet / Excel to Markdown\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              example:\n                url: >-\n                  https://docs.google.com/spreadsheets/d/1WF2KHMPulpin70CA1o6vH2-ZAhKrsm92/edit?usp=drive_link&ouid=107958425101123608031&rtpof=true&sd=true\n      responses:\n        '200':\n          description: Successful response\n          content:\n            application/json: {}\n  /convert/notion:\n    post:\n      tags:\n        - Convert\n      summary: Convert Notion Page to Markdown\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              example:\n                url: >-\n                  https://www.notion.so/trilogy-enterprises/test_bogdan-md-35469c94e208495d93fb4510daa816f0\n                export_child_pages: true\n      responses:\n        '200':\n          description: Successful response\n          content:\n            application/json: {}\n  /convert/postman:\n    post:\n      tags:\n        - Convert\n      summary: Convert Postman Collection to Markdown\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              example:\n                url: >-\n                  https://ws-eng.postman.co/workspace/ProductMind~4f2b8040-ee72-4afe-92d0-b189c4dac3e9/collection/38070356-941aecfa-a192-46a6-98b0-756a76a4693f?action=share&creator=38070356\n      responses:\n        '200':\n          description: Successful response\n          content:\n            application/json: {}\n  /fetch/jira-tickets:\n    post:\n      tags:\n        - Fetch\n      summary: Fetch Jira tickets\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              example:\n                tickets:\n                  - TAI-34\n                  - TAI-36\n      responses:\n        '200':\n          description: Successful response\n          content:\n            application/json: {}\n  /fetch/sql-schema:\n    post:\n      tags:\n        - Fetch\n      summary: Fetch SQL Schema\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              example:\n                user: db_user\n                password: secure_password\n                hostname: db.hostname.com\n                database: sample_database\n                tables:\n                  - table1\n                  - table2\n                  - table3\n                modules:\n                  - module1\n                  - module2\n                skip_cleanup: true\n      responses:\n        '200':\n          description: Successful response\n          content:\n            application/json: {}\n  /write/notion:\n    post:\n      tags:\n        - Write\n      summary: Replace content of a Notion Page from Markdown\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              example:\n                command: replace\n                page_id: 3307018dd8c243e494194c28b0c16678\n                content: |-\n                  # This is an updated Page\n\n                  This is a page with content replaced via the API.\n                  With some bullets:\n                  - bullet 1\n                  - bullet 2\n                  - bullet 3\n                title: API Created Page with a changed title\n      responses:\n        '200':\n          description: Successful response\n          content:\n            application/json: {}\n  /list:\n    post:\n      tags:\n        - Query\n      summary: List files of a company\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              example:\n                command: list_files\n                company: test-company-name\n      responses:\n        '200':\n          description: Successful response\n          content:\n            application/json: {}\n  /query:\n    post:\n      tags:\n        - Query\n      summary: Query the knowledge base\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              example:\n                query: What are the key features of the product?\n                company: test-company-name\n                product: example-product\n                type: ''\n                refresh: false\n                output: docs\n                return_type: document\n                results: 5\n      responses:\n        '200':\n          description: Successful response\n          content:\n            application/json: {}\n  /sync:\n    post:\n      tags:\n        - Sync\n      summary: Refresh data for a company\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              example:\n                company: test-company-name\n                product: example-product\n      responses:\n        '200':\n          description: Successful response\n          content:\n            application/json: {}\n  /remove:\n    post:\n      tags:\n        - Sync\n      summary: Remove data by company and filename\n      description: >-\n        Removes from the knowledge base a previously synced Url\n        (file/page/etc.).\n\n\n        See also: \"Remove data by URL\"\n\n\n        ## Parameters\n\n\n        - `company_name` - name of the company\n            \n        - `file_name` - name of the file that should be removed (e.g. \"Product\n        presentation.pdf\")\n            \n\n        ## Technical details\n\n\n        - the related database entry gets soft deleted\n            \n        - the source, markdown and metadata files get deleted in the S3 buckets\n      requestBody:\n        content:\n          application/json:\n            schema:\n              type: object\n              example:\n                company: test-company-name\n                file_name: test sheet for TAI-36\n      responses:\n        '200':\n          description: Successful response\n          content:\n            application/json: {}\n"},{"id":"49c04d1f-1a91-4cef-9be6-d649c1af898e","name":"Convert GitHub MD to Markdown","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"url\": \"https://github.com/trilogy-group/productmind-tools/blob/main/docs/context-pack/L1.productmind.context.md\"\n}","options":{"raw":{"language":"json"}}},"url":"https://pr131.productmind.trilogy.com/convert/url"},"status":"OK","code":200,"_postman_previewlanguage":"plain","header":[{"key":"Date","value":"Fri, 22 Nov 2024 17:51:38 GMT"},{"key":"Content-Type","value":"text/markdown; charset=utf-8"},{"key":"Content-Length","value":"7416"},{"key":"Connection","value":"keep-alive"},{"key":"x-amzn-RequestId","value":"acd0c554-09a8-4cbb-9972-461dd606f3f6"},{"key":"x-amz-apigw-id","value":"BqOqaFlnoAMECug="},{"key":"X-Amzn-Trace-Id","value":"Root=1-6740c4a8-40fa1c664bb3a15d472d11f4;Sampled=1;Lineage=1:59f458cb:0"}],"cookie":[],"responseTime":null,"body":"---\ntype: product\nname: \"ProductMind\"\ndescription: \"A platform that enables users to easily convert and organize files from Google Drive, Notion, and other sources into a comprehensive knowledge base.\"\nscripts:\n    check:\n        - cwd: \".\"\n          script: \"todo\"\n    fix:\n        - cwd: \".\"\n          script: \"todo\"\n    test:\n        - cwd: \".\"\n          script: \"pytest\"\nfiles:\n    cicd:\n        include:\n            - \".github/workflows/**\"\n    docs:\n        include:\n            - \"docs/**/*.md\"\n    iac:\n        include:\n            - \"deploy/**/*.py\"\n        exclude:\n            - \"deploy/src/scripts/destroy_env.py\"\n---\n\n# Context Pack - ProductMind - L1\n\n## Business Context\n\n### Business Problem\n\nProductMind addresses the challenge of effectively converting and organizing unstructured data from various sources, such as Google Drive, Notion, and PDF documents, into a readily accessible and searchable knowledge base. Many organizations struggle with managing and leveraging this data due to its scattered format, leading to inefficiencies in knowledge sharing, collaboration, and decision-making.\n\n### Vision\n\nProductMind aims to revolutionize knowledge management by providing a seamless and automated solution for converting, organizing, and accessing unstructured data. Our vision is to empower users with a centralized platform that eliminates the need for manual data manipulation, enabling them to easily access, search, and share critical information across their teams.\n\n### How do we Win\n\nProductMind differentiates itself from traditional knowledge management solutions by:\n\n* **Automating Data Conversion:**  ProductMind leverages AI-powered conversion tools to seamlessly transform various file types (PDF, Notion pages, etc.) into searchable Markdown format.\n* **Centralized Knowledge Base:** ProductMind aggregates converted data into a single, searchable knowledge base, simplifying access and reducing information silos.\n* **Flexible Integration:** ProductMind integrates with popular platforms like Google Drive and Notion, allowing users to effortlessly incorporate data from existing workflows.\n\n### Important Business Decisions\n\n* **Choosing the right AI models:**  Selecting powerful and reliable AI models for document conversion and knowledge extraction is paramount. \n* **Balancing features and ease of use:**  ProductMind must strike a balance between offering a rich set of features and maintaining a user-friendly interface. \n* **Prioritizing customer feedback:**  Gathering and responding to customer feedback is crucial for continuous product improvement and customer satisfaction.\n\n## Product Context\n\n### Core Features\n\n* **Automated File Conversion:**  ProductMind automatically converts various file types (PDF, Notion pages, etc.) into searchable Markdown format. \n* **Centralized Knowledge Base:** ProductMind provides a single, searchable repository for all converted content, eliminating information silos.\n* **Integration with Existing Platforms:** ProductMind seamlessly integrates with popular platforms like Google Drive and Notion, enabling effortless data ingestion.\n\n### Important Functional Decisions\n\n* **Prioritizing accurate content extraction:**  ProductMind's AI-powered conversion must ensure high accuracy in extracting relevant data from various file formats.\n* **Creating a robust search functionality:**  A comprehensive search function that allows users to easily find specific information within the knowledge base is crucial.\n* **Implementing a user-friendly content organization system:**  ProductMind must offer intuitive methods for tagging, categorizing, and organizing content for easy navigation.\n\n## Technical Context\n\n### Tech Stack\n\nProductMind leverages a combination of cloud services, backend infrastructure, and AI models:\n\n* **Cloud Services:** AWS (Lambda, S3, DynamoDB, Step Functions, Secret Manager, Bedrock) \n* **Backend:** Python, Flask, Docker, CDK \n* **AI Models:** Claude (Anthropic), OpenAI (GPT-4)\n\n### Technical Architecture\n\n```mermaid\ngraph LR\n    subgraph User Interaction\n        A[Stack AI workflow] --> B[Lambda Functions]\n    end\n    subgraph Backend\n        B --> C[DynamoDB (Data Store)]\n        B --> D[S3 (Storage)] --> G[Bedrock]\n        B --> E[State Machines]\n        B --> F[AI Services (Claude/OpenAI)]\n    end\n```\n\n### Data Model\n\nProductMind's data model is centered around a single DynamoDB table storing information about companies, URLs, and files. The table includes various indexes to facilitate efficient data retrieval.\n\n* **Companies:** Each company has a unique ID and name, allowing users to organize content.\n* **URLs:**  URLs represent external resources from Google Drive, Notion, and other sources. They are associated with companies and classified by type (file or folder).\n\n### Processed files\n* **productmind S3 Bucket:**  Includes both the source and MD converted files\n* **bedrock-productmind S3 Bucket:**  Includes the MD converted files and a metadata file in JSON. Used as the data source for the Bedrock KB.\n\n### Important Technical Decisions\n\n* **Scaling the knowledge base:**  ProductMind's architecture should be designed to handle the growth of the knowledge base and ensure scalability for large volumes of data.\n* **Optimizing AI model usage:**  Balancing the performance of AI models for conversion with cost-effectiveness is essential.\n* **Ensuring data security:**  Implementing robust security measures to protect user data and sensitive information is paramount.\n\n### Established Practices\n\n* **Code organization:**  The codebase follows a modular structure, with well-defined modules for different functionalities, promoting maintainability and testability.\n* **Deployment:**  CDK is employed for infrastructure as code, enabling automated deployments across different environments.\n\n### 3rd party services\n\n* **Google Drive API:**  For accessing and manipulating Google Drive data.\n* **Notion API:**  For retrieving content and metadata from Notion pages.\n* **Anthropic (Claude API):**  For converting PDF documents into Markdown.\n* **OpenAI (GPT-4):**  For converting PDF documents into Markdown.\n* **Bedrock:**  For building a knowledge base and providing AI-powered question answering functionality.\n\n### 3rd party libraries\n\n* **pydantic:**  For data validation and model definition.\n* **notion-client:**  For interacting with the Notion API.\n* **openai:** For interacting with the OpenAI API.\n* **anthropic:** For interacting with the Anthropic API.\n* **pdf2image:**  For converting PDF documents into PNG images.\n* **aws_cdk:** For defining and deploying AWS infrastructure.\n\n### Environments\n\nProductMind utilizes multiple environments to manage deployments:\n\n* **PR:** For developers to build and test new features. Deployed automatically from each PR.\n* **Production:** The live environment accessible to end-users. Deployed automatically from main branch.\n\n## Modules\n\n* **Sync company data:**  Handles the ingestion and refreshing of data for a company. Including traversing input folders and converting source files to markdown. For more details, refer to [L2.sync-company-data.context.md](./L2.sync-company-data.context.md).\n* **Source file conversion:**  The process of converting source files (PDF, Notion pages, etc.) into Markdown format. For more details, refer to [L2.source-file-conversion.context.md](./L2.source-file-conversion.context.md).\n"},{"id":"3a214494-b22f-45ad-bdcb-43a9868dcd70","name":"Convert GitHub TXT to Markdown","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"url\": \"https://github.com/trilogy-group/productmind-tools/blob/main/functions/pythonLambdas/requirements.txt\"\n}","options":{"raw":{"language":"json"}}},"url":"https://pr131.productmind.trilogy.com/convert/url"},"status":"OK","code":200,"_postman_previewlanguage":"plain","header":[{"key":"Date","value":"Fri, 22 Nov 2024 17:52:19 GMT"},{"key":"Content-Type","value":"text/markdown; charset=utf-8"},{"key":"Content-Length","value":"373"},{"key":"Connection","value":"keep-alive"},{"key":"x-amzn-RequestId","value":"69cf0389-7681-42dd-b94f-cd482568c17b"},{"key":"x-amz-apigw-id","value":"BqOwvH6eoAMEonw="},{"key":"X-Amzn-Trace-Id","value":"Root=1-6740c4d1-0fe79143458950753616fb85;Sampled=1;Lineage=1:59f458cb:0"}],"cookie":[],"responseTime":null,"body":"boto3==1.34.117\nbotocore==1.34.117\naiobotocore==2.13.1\ngoogle-api-python-client==2.131.0\ngoogle-auth==2.29.0\ngoogle-auth-httplib2==0.2.0\ngoogle-auth-oauthlib==1.2.0\npydantic==2.7.2\npydantic_core==2.18.3\nrequests==2.32.3\nstructlog==24.2.0\nopenai==1.52.0\nanthropic==0.30.1\npynamodb==6.0.1\nnotion-client==2.2.1\nbackoff==2.2.1\nPyGithub==2.4.0\nlitellm==1.51.1\nLiteLLMJson==0.0.7"}],"_postman_id":"9af0f420-5d91-4655-ac23-2bbc4e4aa203"},{"name":"Convert PDF to Markdown","id":"5864dd86-e2c7-4d1f-a203-28a4767239e0","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"url\": \"https://drive.google.com/file/d/1LSiSyhH8La9Pm-GQ40wFanOg6Znob-cQ/view?usp=sharing\",\n    \"force_reprocess\": true\n}","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/convert/pdf","description":"<p>This endpoint converts PDF files to Markdown format. It allows users to provide a URL to a PDF file stored in Google Drive, which the service will then download, process, and convert to Markdown. The converted Markdown is returned by the endpoint and is cached in an S3 bucket for speeding up future access.</p>\n<h3 id=\"parameters\">Parameters:</h3>\n<ul>\n<li><p><code>url</code> (string, required): The URL of the PDF file stored in Google Drive to be converted.</p>\n</li>\n<li><p><code>start_page</code> (int, optional): The first page to process. Default: 1</p>\n</li>\n<li><p><code>end_page</code> (int, optional): The last page to process. Default: null (so all pages will be processed)</p>\n</li>\n<li><p><code>llm</code> (string, optional): The LLM to use for conversion. Options:</p>\n<ul>\n<li><p><code>claude-3-7-sonnet</code> (default)</p>\n</li>\n<li><p><code>claude-3-5-sonnet</code></p>\n</li>\n<li><p><code>gpt-4o</code></p>\n</li>\n<li><p><code>gpt-4.1</code></p>\n</li>\n<li><p><code>gemini-2.0-flash</code></p>\n</li>\n<li><p><code>gemini-2.5-pro</code></p>\n</li>\n</ul>\n</li>\n<li><p><code>return_mode</code> (string, optional): Controls how the markdown content is returned. Options:</p>\n<ul>\n<li><p><code>direct</code>: Returns the markdown content in the response body</p>\n</li>\n<li><p><code>s3_url</code>: Returns an s3 path with the generated markdown. Useful when used with automations (e.g. step functions) where downstream steps have access to the S3 bucket.</p>\n</li>\n<li><p><code>auto</code>(default): For small files <code>direct</code> for larger ones <code>s3_url</code>. Cutoff is currently at 256KB markdown (step function limit)</p>\n</li>\n</ul>\n</li>\n</ul>\n<p>All parameters should be passed in the request body as JSON.</p>\n<blockquote>\n<p><strong>Note:</strong> The Google Drive file must be shared with the <code>cpm-diligence@trilogy.com</code> group for this endpoint to access and process it.</p>\n</blockquote>\n","urlObject":{"protocol":"https","path":["convert","pdf"],"host":["productmind.trilogy.com"],"query":[],"variable":[]}},"response":[{"id":"bfa3782c-c766-4ad6-96ee-72348264abab","name":"Convert PDF to Markdown","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"url\": \"https://drive.google.com/file/d/1ljWPbWQImvfoY3V5ruBMoahh1nBdCBKr/view\"\n}","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/convert/pdf"},"status":"OK","code":200,"_postman_previewlanguage":"text","header":[{"key":"Content-Type","value":"text/markdown; charset=utf-8","description":"","type":"text","enabled":true}],"cookie":[],"responseTime":null,"body":"# Page 1\n\n# Act-On Executive Summary\n\n![act-on logo](act-on-logo.png)\n\n# Page 2\n\n# The Modern Platform Fueling MarTech 3.0\n\n## Daily Clicks\nShows the clicks per day of selected timeframe.\n\n..."}],"_postman_id":"5864dd86-e2c7-4d1f-a203-28a4767239e0"},{"name":"Convert Google Doc / Word to Markdown","id":"70735366-58ca-4332-bd16-875cd139fc07","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"url\": \"https://docs.google.com/document/d/1-CJEZNzjNq6i_JHA9_9R-8Jrm5FEfzyRFQP_v2esAdY/edit?usp=drive_link\"\n}\n","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/convert/gdoc","description":"<p>This endpoint converts Google Docs to Markdown format. It allows users to provide a URL to a Google Doc, which the service will then download, process, and convert to Markdown. The converted Markdown is returned by the endpoint and is cached in an S3 bucket for speeding up future access.</p>\n<h3 id=\"parameters\">Parameters:</h3>\n<ul>\n<li><code>url</code> (string, required): The URL of the Google Doc to be converted.</li>\n</ul>\n<p>All parameters should be passed in the request body as JSON.</p>\n<blockquote>\n<p><strong>Note:</strong> The Google Drive file must be shared with the <code>cpm-diligence@trilogy.com</code> group for this endpoint to access and process it.</p>\n</blockquote>\n","urlObject":{"protocol":"https","path":["convert","gdoc"],"host":["productmind.trilogy.com"],"query":[],"variable":[]}},"response":[{"id":"86d5c7f9-b93c-405d-a589-c56ebe6fec60","name":"Example Response","originalRequest":{"method":"GET","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n  \"url\": \"https://docs.google.com/document/d/1-CJEZNzjNq6i_JHA9_9R-8Jrm5FEfzyRFQP_v2esAdY/edit?usp=drive_link\"\n}\n","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/convert/gdoc"},"status":"OK","code":200,"_postman_previewlanguage":"markdown","header":[{"key":"Content-Type","value":"text/markdown","enabled":true}],"cookie":[],"responseTime":null,"body":"# Sample Google Doc\n\nThis is the converted content of the Google Doc.\n\n## Section 1\n\nContent of section 1\n\n## Section 2\n\nContent of section 2...`"}],"_postman_id":"70735366-58ca-4332-bd16-875cd139fc07"},{"name":"Convert Google Sheet / Excel to Markdown","id":"07ba90d2-d056-4296-b74f-9b498016d8d4","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"url\": \"https://docs.google.com/spreadsheets/d/1_rjDZyvsnGj8i8TncF1BlyLssaCJrPsGMBZmgpR_0EI/edit\"\n}\n","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/convert/gsheet","description":"<p>This endpoint converts Google Sheets to Markdown format. It allows users to provide a URL to a Google Sheet, which the service will then download, process, and convert to Markdown. The converted Markdown is returned by the endpoint and is cached in an S3 bucket for speeding up future access.</p>\n<h3 id=\"parameters\">Parameters:</h3>\n<p><strong>Request</strong>:</p>\n<ul>\n<li><p><code>url</code> (string / UrlConfig, optional): The URL of the Google Sheet to be converted.</p>\n</li>\n<li><p><code>urls</code> (array of string / UrlConfig, optional): List of Google Sheet urls to be converted.</p>\n</li>\n<li><p><code>conversion_mode</code> (enum, optional): Controls how the data will be written in the markdown results. Options:</p>\n<ul>\n<li><p><code>markdown</code> (default): every sheet will be converted into markdown tables. Human + machine readable.</p>\n</li>\n<li><p><code>csv</code>: tables will be added as csv content. Less human readable.</p>\n</li>\n</ul>\n</li>\n</ul>\n<p>Note that either <code>url</code> or <code>urls</code> field is required. When both are filled they will all be processed.</p>\n<p>When there are multiple urls provided the results will include each converted docs one after another.</p>\n<p><code>UrlConfig</code> <strong>object fields:</strong></p>\n<ul>\n<li><p><code>url</code> (string, required): The URL of the Google Sheet to be converted.</p>\n</li>\n<li><p><code>sheet</code> (string, optional): If provided only the given sheet will be converted. All the other sheets will be ignored.<br />  Note: only supported for <code>csv</code> conversion mode</p>\n</li>\n</ul>\n<p>All parameters should be passed in the request body as JSON.</p>\n<blockquote>\n<p><strong>Note:</strong> The Google Drive file must be shared with the <code>cpm-diligence@trilogy.com</code> group for this endpoint to access and process it.</p>\n</blockquote>\n","urlObject":{"protocol":"https","path":["convert","gsheet"],"host":["productmind.trilogy.com"],"query":[],"variable":[]}},"response":[{"id":"2480c9dc-531d-4cc7-8dfc-e8fca144d2b4","name":"Convert Google Sheet / Excel to Markdown","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"url\": \"https://docs.google.com/spreadsheets/d/1WF2KHMPulpin70CA1o6vH2-ZAhKrsm92/edit?usp=drive_link&ouid=107958425101123608031&rtpof=true&sd=true\"\n}\n","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/convert/gsheet"},"status":"OK","code":200,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"text/markdown","description":"","enabled":true,"type":"text"}],"cookie":[],"responseTime":null,"body":"# Sample Google Sheet\n\n| Column 1 | Column 2 | Column 3 |\n|----------|----------|----------|\n| Value 1  | Value 2  | Value 3  |\n| Value 4  | Value 5  | Value 6  |\n\n## Sheet 2\n\n| Column A | Column B |\n|----------|----------|\n| Value A  | Value B  |\n| Value C  | Value D  |`\n| Value E  | Value F  |`"},{"id":"f4216480-8e8b-46a1-9dfb-0cf0c1ecc4b5","name":"Convert Google Sheet / Excel to Markdown","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"urls\": [\n    {\n        \"url\": \"https://docs.google.com/spreadsheets/d/1WF2KHMPulpin70CA1o6vH2-ZAhKrsm92/edit?usp=drive_link&ouid=107958425101123608031&rtpof=true&sd=true\"\n    },\n    {\n        \"url\": \"https://docs.google.com/spreadsheets/d/19LuYr1MeoS7gHpxn7gaSL6tL2Zb6R4hJndwNZo7ZwcQ/edit?gid=0#gid=0\",\n        \"sheet\": \"priorities\"\n    }\n  ],\n  \"conversion_mode\": \"csv\"\n}\n","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/convert/gsheet"},"status":"OK","code":200,"_postman_previewlanguage":"plain","header":[{"key":"Date","value":"Fri, 28 Mar 2025 09:06:27 GMT"},{"key":"Content-Type","value":"text/markdown; charset=utf-8"},{"key":"Content-Length","value":"768"},{"key":"Connection","value":"keep-alive"},{"key":"x-amzn-RequestId","value":"45f36526-1de0-44cd-bf28-2931bac0ea19"},{"key":"x-amz-apigw-id","value":"IIT3CEFzIAMEh5Q="},{"key":"X-Amzn-Trace-Id","value":"Root=1-67e66693-4e185b4f45114a655be9ae40;Sampled=1;Lineage=1:92903467:0"}],"cookie":[],"responseTime":null,"body":"# Demo excel file (source url: https://docs.google.com/spreadsheets/d/1WF2KHMPulpin70CA1o6vH2-ZAhKrsm92/edit?usp=drive_link&ouid=107958425101123608031&rtpof=true&sd=true)\n\n\n## Sheet: prios ###\nFeature,Category,Status,Owner,Size,Launch,Notes\nabbavecr,Category 1,Not started,,XS,Q1,\nklklkj aferkjh,Category 2,In progress,,S,Q2,\nfgg,Category 3,Blocked,,M,Q3,\ngggghhg,Category 4,Launched,,L,Q4,\n\n\n# Just a test sheet (source url: https://docs.google.com/spreadsheets/d/19LuYr1MeoS7gHpxn7gaSL6tL2Zb6R4hJndwNZo7ZwcQ/edit?gid=0#gid=0)\n\n\n## Sheet: priorities ###\nFeature,Category,Status,Owner,Size,Launch,Notes\nabbavecr,Category 1,Not started,,XS,Q1,\nklklkj aferkjh,Category 2,In progress,,S,Q2,\nkkds,Category 3,Blocked,,M,Q3,\ndsjajknasd,Category 4,Launched,,L,Q4,\njk,,,,,,\n\n\n"}],"_postman_id":"07ba90d2-d056-4296-b74f-9b498016d8d4"},{"name":"Convert Notion Page to Markdown","id":"46a702fa-f0b9-45e8-a946-afcb9bb3dde3","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"url\": \"https://www.notion.so/trilogy-enterprises/Reconciliation-term-subject-prompt-13685e927d3180a784f1f800754cf4f1\",\n  \"export_child_pages\": false,\n  \"use_proxy\": true\n}\n","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/convert/notion","description":"<p>This endpoint converts Notion pages to Markdown format. It allows users to provide a URL to a Notion page, which the service will then process and convert to Markdown. The converted Markdown is returned by the endpoint and is cached in an S3 bucket for speeding up future access.</p>\n<h3 id=\"parameters\">Parameters:</h3>\n<ul>\n<li><p><code>url</code> (string, required): The URL of the Notion page to be converted.</p>\n</li>\n<li><p><code>export_child_pages</code> (boolean, optional): Whether to include child pages in the conversion. Default is false.</p>\n</li>\n<li><p><code>use_proxy</code> (boolean, optional): Whether to use the proxy (with request-response cache) mainly created for Doc Gen processing. Default is false.</p>\n</li>\n</ul>\n<p>All parameters should be passed in the request body as JSON.</p>\n<blockquote>\n<p><strong>Note:</strong> The Notion page must be shared with the ProductMind-Export-Import integration for this endpoint to access and process it.<br />To share the page with the exporter, follow these steps:<br />1. Open the page in Notion.<br />2. Open the 'three dots' menu in the top-right corner.<br />3. Ensure that 'ProductMind-Export-Import' is listed under 'Connections'. If not, add it.</p>\n</blockquote>\n","urlObject":{"protocol":"https","path":["convert","notion"],"host":["productmind.trilogy.com"],"query":[],"variable":[]}},"response":[{"id":"98642531-84e3-4edd-8e75-383fe5f50a18","name":"Convert Notion Page to Markdown","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"url\": \"https://www.notion.so/trilogy-enterprises/test_bogdan-md-35469c94e208495d93fb4510daa816f0\",\n  \"export_child_pages\": true,\n  \"use_proxy\": false\n}\n","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/convert/notion"},"status":"OK","code":200,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"text/markdown","description":"","enabled":true,"type":"text"}],"cookie":[],"responseTime":null,"body":"# Sample Notion Page\n\nThis is the converted content of the Notion page.\n\n## Child Page 1\n\nContent of child page 1...\n\n## Child Page 2\n\nContent of child page 2..."}],"_postman_id":"46a702fa-f0b9-45e8-a946-afcb9bb3dde3"},{"name":"Convert Postman Collection to Markdown","id":"c24f9cd0-e91d-424d-90b2-62e2a1128eea","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"url\": \"https://ws-eng.postman.co/workspace/ProductMind~4f2b8040-ee72-4afe-92d0-b189c4dac3e9/collection/38070356-941aecfa-a192-46a6-98b0-756a76a4693f?action=share&creator=38070356\"\n}\n","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/convert/postman","description":"<p>This endpoint converts Postman collections to Markdown format. It allows users to provide a URL to a Postman collection or folder, which the service will then download, process, and convert to Markdown. The converted Markdown is returned by the endpoint and is cached in an S3 bucket for speeding up future access.</p>\n<h3 id=\"parameters\">Parameters:</h3>\n<ul>\n<li><code>url</code> (string, required): The URL of the Postman collection or folder to be converted.</li>\n</ul>\n<p>All parameters should be passed in the request body as JSON.</p>\n<blockquote>\n<p><strong>Note:</strong> The following URL formats are supported for Postman collections:<br />- Workspace folder: <code>https://ws-eng.postman.co/workspace/Platform-Prod~66ec436e-5fcd-43ad-964c-f70d5ca1225f/folder/31124709-c9060ee9-6b7c-4d32-861c-7ff22d5d9c60</code><br />- Collection: <code>https://ws-eng.postman.co/workspace/ProductMind~4f2b8040-ee72-4afe-92d0-b189c4dac3e9/collection/38070356-941aecfa-a192-46a6-98b0-756a76a4693f?action=share&amp;creator=38070356</code><br />- Workspace folder (alternative format): <code>https://ws-eng.postman.co/workspace/ProductMind~4f2b8040-ee72-4afe-92d0-b189c4dac3e9/folder/38070356-b86b8070-d4d8-44b4-9361-c47d3e2256b2?action=share&amp;source=copy-link&amp;creator=38070356&amp;ctx=documentation</code><br />- Collection (alternative format): <code>https://ws-eng.postman.co/workspace/Platform-Prod~66ec436e-5fcd-43ad-964c-f70d5ca1225f/collection/31124709-d038145a-a2fd-46f9-8cd1-f6024afbbf72   </code>- Workspace folder (without workspace name): <code>https://ws-eng.postman.co/workspace/4f2b8040-ee72-4afe-92d0-b189c4dac3e9/folder/38070356-5f19b4dd-c3e9-48cd-9383-7d4d030f74ed?action=share&amp;source=copy-link&amp;creator=38070356&amp;ctx=documentation</code></p>\n</blockquote>\n","urlObject":{"protocol":"https","path":["convert","postman"],"host":["productmind.trilogy.com"],"query":[],"variable":[]}},"response":[{"id":"34f13acd-99c1-4380-960e-6aa61bc975bc","name":"Example Response","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n  \"url\": \"https://ws-eng.postman.co/workspace/Platform-Prod~66ec436e-5fcd-43ad-964c-f70d5ca1225f/collection/31124709-d038145a-a2fd-46f9-8cd1-f6024afbbf72\"\n}\n","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/convert/postman"},"status":"OK","code":200,"_postman_previewlanguage":"markdown","header":[{"key":"Content-Type","value":"text/markdown","enabled":true}],"cookie":[],"responseTime":null,"body":"# Sample Postman Collection\n\n## Endpoint 1: GET /api/resource\n\nDescription of endpoint 1..\n\n### Request\n\n\\`\\`\\`http\nGET /api/resource HTTP/1.1\nHost: api.example.com\n\\`\\`\\`\n\n### Response\n\n\\`\\`\\`json\n{\n  \"key\": \"value\"\n}\n\\`\\`\\`\n\n## Endpoint 2: POST /api/resource\n\nDescription of endpoint 2...\n\n### Request\n\n\\`\\`\\`http\nPOST /api/resource HTTP/1.1\nHost: api.example.com\nContent-Type: application/json\n\n{\n  \"data\": \"example\"\n}\n\\`\\`\\`\n\n### Response\n\n\\`\\`\\`json\n{\n  \"id\": \"123\",\n  \"status\": \"created\"\n}\n\\`\\`\\``"}],"_postman_id":"c24f9cd0-e91d-424d-90b2-62e2a1128eea"},{"name":"Convert Video to Transcript","id":"96ba21c2-554f-4f5a-acdb-eb613e43553f","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"url\": \"https://drive.google.com/file/d/1aTwPU1yBnFoIEsXB0IBQXlGEduTicCt0/view\",\n  \"force_reprocess\": false\n}\n","options":{"raw":{"language":"json"}}},"url":"https://pr193.productmind.trilogy.com/convert/video","description":"<p>This endpoint converts mp4 videos to their transcript in plain text. It allows users to provide a URL to a video on Google Drive, which the service will then download and transcribe. The converted transcription is returned by the endpoint and is cached in an S3 bucket for speeding up future access.</p>\n<p>If there is a transcript already next to the video file on Google Drive then that file will be used instead of generating a new one. See note below about permissions.</p>\n<h3 id=\"transcript-file-naming-convention\">Transcript file naming convention</h3>\n<p>The following transcript naming conventions are recognized:</p>\n<ol>\n<li><p>file with the same name with .txt or .docx extension</p>\n</li>\n<li><p>Google Meet recording naming format, e.g</p>\n<ol>\n<li><p>Waleed Bin Inam Satti and Bogdan Tenea – 2024/09/09 13:34 EEST – Transcript</p>\n</li>\n<li><p>Waleed Bin Inam Satti and Bogdan Tenea – 2024/09/09 13:34 EEST – Recording</p>\n</li>\n</ol>\n</li>\n<li><p><a href=\"http://read.ai/\">read.ai</a> recording naming format, e.g.</p>\n<ol>\n<li><p>Project Passage _ Product Demo (Trilogy) Recording.mp4</p>\n</li>\n<li><p>Project Passage _ Product Demo (Trilogy) Transcript.txt</p>\n</li>\n</ol>\n</li>\n</ol>\n<p>We support txt, docx and google doc formats for the transcripts, they all will be converted to plain text (.txt).</p>\n<h3 id=\"parameters\">Parameters:</h3>\n<ul>\n<li><p><code>url</code> (string, required): The URL of the Postman collection or folder to be converted.</p>\n</li>\n<li><p><code>provider</code> (string, optional, default: <code>deepgram</code>): One of the supported providers that can be used for transcribing:</p>\n<ul>\n<li><p><code>aws</code> - using Amazon Transcribe</p>\n</li>\n<li><p><code>deepgram</code> (default) - using Deepgram nova-3 model</p>\n</li>\n<li><p><code>deepgram-nova-2</code> - using previous version of Deepgram model (nova-2)</p>\n</li>\n<li><p><code>google</code> - using Google Speech (chirp 2 model) - note that this option doesn't support speaker recognition and timestamps</p>\n</li>\n</ul>\n</li>\n<li><p><code>force_reprocess</code> (boolean, optional, default: <code>false</code>): Reprocess the video even if the results are already cached. You shouldn't normally use this, but can be helpful when evaluating different providers for the same file.</p>\n</li>\n</ul>\n<h3 id=\"note-on-permissions\">Note on permissions</h3>\n<ul>\n<li><p>In order to check and find a transcript file in Google drive next to the video the <code>cpm-diligence@trilogy.com</code> service account needs to have view access to the folder containing the video and transcript (otherwise we can't check whether there is another file next to the video)</p>\n</li>\n<li><p>In order to transcribe a video the <code>cpm-diligence@trilogy.com</code> service account needs to have access to it, and the video needs to allow viewers to download the video (you can change this on the share dialog under the settings clicking the cog icon). This is sometimes for meeting recordings off by default.</p>\n</li>\n</ul>\n","urlObject":{"protocol":"https","path":["convert","video"],"host":["pr193","productmind.trilogy.com"],"query":[],"variable":[]}},"response":[{"id":"eb748a86-8702-4045-b157-510f40b04170","name":"Example Response","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n  \"url\": \"https://drive.google.com/file/d/1P_E5F2dDisTr7vG-x-g-PuLVGB4BJW9D/view?usp=drive_link\"\n}\n","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/convert/video"},"status":"OK","code":200,"_postman_previewlanguage":"markdown","header":[{"key":"Content-Type","value":"text/plain","enabled":true}],"cookie":[],"responseTime":null,"body":"00:01 - Speaker 0\nThis is a sample video that we can use I integration tests to test video transcriptions to text and it doesn't serve any other purpose. This is the Google Drive folder with the integration files. This is where it will get added.\n"}],"_postman_id":"96ba21c2-554f-4f5a-acdb-eb613e43553f"}],"id":"5f19b4dd-c3e9-48cd-9383-7d4d030f74ed","description":"<p>This folder contains endpoints for <strong>converting various file types to Markdown format</strong>. Conversion results are <strong>cached</strong>, so you can safely call the endpoints multiple times with the same input.</p>\n<p>These endpoints enable seamless integration of file conversion capabilities into your workflow, making it easy to standardize content across different platforms and file formats.</p>\n","_postman_id":"5f19b4dd-c3e9-48cd-9383-7d4d030f74ed"},{"name":"Extract","item":[{"name":"Extract entities from video from summary checklist","id":"225d71e0-fb46-468c-9f5f-0d3b0185847b","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"token":""},"isInherited":false},"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \n  \"product_name\": \"Tivian DXI\",\n  \"product_context\": \"\",\n  \"notification_receiver_emails\": [\"akos.orban@trilogy.com\"],\n  \"file_inputs\": [\n    { \"file_link\": \"https://drive.google.com/file/d/1Mk3H4FavKUrlFmFXnkhnIclXvzyamovp/view?usp=drive_link\", \"start_offset\": null, \"end_offset\": null }\n  ],\n  \"topics\": [\n    {\n        \"topic\": \"Architecture Overview\",\n        \"checklist\": \"Discuss the dual hosting infrastructure (AWS & Data Center). Overview of microservices and monolithic components.\"\n    }\n  ],\n  \"generate_topics_from_content\": true\n}","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/extract/video/from_checklist","description":"<p>Allows extracting entities from video based on only a summary that includes the topics and a checklists. There can be one or more topics provided as input, additional ones will be discovered by AI.</p>\n<p>This version is to be used when the expected output schema for the topics is unknown. If you know the schema then use the sister endpoint: /extract/video/from_schema</p>\n<p><em>Note that this endpoint requires a Bearer auth token to be specifed.</em></p>\n<h2 id=\"parameters\">Parameters</h2>\n<ul>\n<li><p><code>product_name</code> (string, required): Name of the product evaluated - currently only used in prompts, in future could be used for KB queries</p>\n</li>\n<li><p><code>product_context</code> (string, optional): Additional context in markdown format passed to extraction</p>\n</li>\n<li><p><code>notification_receiver_emails</code> (array of strings, required): List of email addresses where the result emails will be sent by the Video processing.</p>\n</li>\n<li><p><code>file_inputs</code> (array of objects): Array of video files with file link, start offset, and end offset.</p>\n<ul>\n<li><p><code>file_link</code> (string): Link to the Google drive video file.</p>\n</li>\n<li><p><code>start_offset</code> (int?): Start offset for the video (seconds). Optional, defaults to the start of the video.</p>\n</li>\n<li><p><code>end_offset</code> (int?): End offset for the video (seconds). Optional, defaults to the end of the video.</p>\n</li>\n</ul>\n</li>\n<li><p><code>topics</code> (array of objects): Array of the topics that you want to extract from the video. Cannot be empty if <code>generate_topics_from_content</code> is false.</p>\n<ul>\n<li><p><code>topic</code> (string): Title for the topic</p>\n</li>\n<li><p><code>checklist</code> (string?): Checklist for items that should be covered under the topic. This is not the final exhaustive list, and the topic will contain more information as well. Can be omitted.</p>\n</li>\n</ul>\n</li>\n<li><p><code>generate_topics_from_content</code> (boolean?): Indicates whether we should use AI to generate more topics for extraction using the content. Defaults to true. Cannot be set to false if <code>topics</code> is empty.</p>\n</li>\n<li><p><code>entity_extraction_prompt_templates</code> (string?): The notion URL for DocGen's entity extraction prompts. Defaults to <a href=\"https://www.notion.so/trilogy-enterprises/DocGen-Input-Prompt-Templates-12a85e927d31807b886aff531003266e\">this</a> template. These contain placeholders for topics, so they can be used across topics.</p>\n</li>\n<li><p><code>entity_extraction_prompts_filled</code> (string?): The Notion URL where the dynamically generated schema and extraction prompts are stored, before being used for topic-level extraction. Defaults to <a href=\"https://www.notion.so/trilogy-enterprises/Updated-Prompts-032abc0b5a024b56a9940c53b9cf3c13\">this</a>. This is essentially the the <code>entity_extraction_prompt_templates</code> with topic information filled in and with the generated schema.</p>\n</li>\n</ul>\n<h2 id=\"results\">Results</h2>\n<p>The response will indicate whether the request was successful, or there were validation errors in your request.</p>\n<p>Results will be emailed to the given notification addresses, they will <strong>not</strong> be returned by the endpoint.</p>\n","urlObject":{"protocol":"https","path":["extract","video","from_checklist"],"host":["productmind.trilogy.com"],"query":[],"variable":[]}},"response":[],"_postman_id":"225d71e0-fb46-468c-9f5f-0d3b0185847b"},{"name":"Extract entities from video with structured schema","id":"15876bf7-be5e-4958-9f96-7b581ed80364","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"token":""},"isInherited":false},"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \n  \"product_name\": \"Contently\",\n  \"product_context\": \"Content marketing platform for brands and agencies to create, manage, and distribute content across multiple channels.\",\n  \"notification_receiver_emails\": [\"akos.orban@trilogy.com\"],\n  \"file_inputs\": [\n    { \"file_link\": \"https://drive.google.com/file/d/1eQFyKrgNJ0rw5_q_n1JfTbdpEAN-VCJn/view?usp=drive_link\", \"start_offset\": null, \"end_offset\": null }\n  ],\n  \"topics\": [\n    {\n        \"topic\": \"Customer Pain Points\",\n        \"checklist\": \"Extract pains, and related features and benefits for Contently\",\n        \"schema_and_entity_extraction_prompts\": \"https://www.notion.so/trilogy-enterprises/Pains-Features-Benefits-Doc-Gen-Prompts-Rakshit-Test-12385e927d31801e8d98f2efba26e700\"\n    }\n  ],\n  \"generate_topics_from_content\": false\n}","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/extract/video/from_schema","description":"<p>Allows extracting entities from video based on a pre-defined structured schema for the given entities.</p>\n<p>This version is to be used when the expected output schema is already well defined and known. If you don't have a well defined schema, just the list of topics, then use sister endpoint: /extract/video/from_checklist</p>\n<p><em>Note that this endpoint requires a Bearer auth token to be specifed.</em></p>\n<h2 id=\"parameters\">Parameters</h2>\n<ul>\n<li><p><code>product_name</code> (string, required): Name of the product evaluated - currently only used in prompts, in future could be used for KB queries</p>\n</li>\n<li><p><code>product_context</code> (string, optional): Additional context in markdown format passed to extraction</p>\n</li>\n<li><p><code>notification_receiver_emails</code> (array of strings, required): List of email addresses where the result emails will be sent by the Video processing.</p>\n</li>\n<li><p><code>file_inputs</code> (array of objects): Array of video files with file link, start offset, and end offset.</p>\n<ul>\n<li><p><code>file_link</code> (string): Link to the Google drive video file.</p>\n</li>\n<li><p><code>start_offset</code> (int?): Start offset for the video (seconds). Optional, defaults to the start of the video.</p>\n</li>\n<li><p><code>end_offset</code> (int?): End offset for the video (seconds). Optional, defaults to the end of the video.</p>\n</li>\n</ul>\n</li>\n<li><p><code>topics</code> (array of objects): Array of the topics that you want to extract from the video. Cannot be empty if <code>generate_topics_from_content</code> is false.</p>\n<ul>\n<li><p><code>topic</code> (string): Title for the topic</p>\n</li>\n<li><p><code>checklist</code> (string?): Checklist for items that should be covered under the topic. This is not the final exhaustive list, and the topic will contain more information as well. Can be omitted.</p>\n</li>\n<li><p><code>schema_and_entity_extraction_prompts</code> (string): Notion page URL for your custom schema and entity extraction prompts. This should point to a page similar to this <a href=\"https://www.notion.so/trilogy-enterprises/Pains-Features-Benefits-Doc-Gen-Prompts-9397b02357b5475c90a46d45c8a08f4c\">example</a>.</p>\n</li>\n</ul>\n</li>\n<li><p><code>generate_topics_from_content</code> (boolean?): Indicates whether we should use AI to generate more topics for extraction using the content. Defaults to true. Cannot be set to false if <code>topics</code> is empty.</p>\n</li>\n<li><p><code>entity_extraction_prompt_templates</code> (string?): The notion URL for DocGen's entity extraction prompts. Defaults to <a href=\"https://www.notion.so/trilogy-enterprises/DocGen-Input-Prompt-Templates-12a85e927d31807b886aff531003266e\">this</a> template. These contain placeholders for topics, so they can be used across topics.</p>\n</li>\n</ul>\n<h2 id=\"results\">Results</h2>\n<p>The response will indicate whether the request was successful, or there were validation errors in your request.</p>\n<p>Results will be emailed to the given notification addresses, they will <strong>not</strong> be returned by the endpoint.</p>\n","urlObject":{"protocol":"https","path":["extract","video","from_schema"],"host":["productmind.trilogy.com"],"query":[],"variable":[]}},"response":[],"_postman_id":"15876bf7-be5e-4958-9f96-7b581ed80364"},{"name":"Extract details from contracts","id":"46d3604b-0cfb-4f0c-a999-5ead29d192ce","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"company\": \"quark_individual\",\n    \"contracts\": [\n        \"https://drive.google.com/drive/folders/1s_rc5UDQlEgeIIRTQdsMb9QXaJzT-jOd\",\n        \"https://drive.google.com/drive/folders/1GtWNskXS7tsUBDkdv593H0LSm-kah202\",\n        \"https://drive.google.com/drive/folders/1HAsr9w9jTG0FdiER-3yKsKRQJA_IlUgn\",\n        \"https://drive.google.com/drive/folders/1fzNB8T4C--V9Xqk6LcgFIeIWLDYKhryM?usp=sharing\",\n        \"https://drive.google.com/drive/folders/1T4z_lZCG0_sG8lkl0laD7WNwETYIaU2N?usp=drive_link\",\n        \"https://drive.google.com/drive/folders/12KSDn9Fo_r78SCSqexnd_QofPQfvMKej\",\n        \"https://drive.google.com/file/d/1LSiSyhH8La9Pm-GQ40wFanOg6Znob-cQ/view\"\n    ],\n    \"notification_receiver_emails\": [\n        \"muhammad.ishaq@trilogy.com\"\n    ],\n    \"llm_for_extraction\": \"gemini-3-pro-preview\",\n    \"folder_handling_mode\": \"all_pdfs\",\n    \"attempt_dedup_across_input_lines\": false,\n    \"skip_cache\": true,\n    \"force_reprocess_pdfs\": true,\n    \"arr_as_of\": \"2025-12-31\",\n    // \"max_folder_groups_per_chunk\": 80,\n    \"prompt_label\": \"latest\"\n}","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/extract/contracts","description":"<p>EXPERIMENTAL</p>\n<p>Allows extracting details from contracts</p>\n<h2 id=\"parameters\">Parameters</h2>\n<ul>\n<li><p><code>company</code> (string, required): Name of the Company of which contracts are processed</p>\n</li>\n<li><p><code>source</code> (object, optional): Google Sheet source for the contracts to process</p>\n<ul>\n<li><p><code>url</code> (string, required): URL of the Google Sheet</p>\n</li>\n<li><p><code>sheet_name</code> (string, optional): Name of the sheet to use. If not specified will use the first one.</p>\n</li>\n<li><p><code>document_column_name</code> (string, required): Name of the column containing the Google Drive URL to the PDF of the contract</p>\n</li>\n<li><p><code>document_id_column_name</code> (string, optional): Name of the column containing a unique contract identifier. If provided, this ID will be included in the output for mapping purposes.</p>\n</li>\n<li><p><code>limit</code> (int, optional): Number of contracts to process. <strong>Default</strong>: no limit</p>\n</li>\n<li><p><code>offset</code> (int, optional): From which contract to start processing. <strong>Default</strong>: 0</p>\n</li>\n<li><p><code>filters</code> (object, optional): Filter conditions to apply on the source sheet.</p>\n<ul>\n<li><p>column (string, required): Name of the column to filter on</p>\n</li>\n<li><p>value (string, required): Value to match in the filter column</p>\n</li>\n<li><p>operator (string, required): Comparison operator to use. Supported values: \"&gt;\", \"&lt;\", \"=\", \"!=\", \"&gt;=\", \"&lt;=\"</p>\n</li>\n</ul>\n</li>\n</ul>\n</li>\n<li><p><code>contracts</code> (array of strings, optional): The list of contracts to process, each entry should be the url of a Google Drive PDF contract. Entries can also point to Google Drive folders, in such cases all PDFs will be resolved from the folder and used for the extraction</p>\n</li>\n<li><p><code>notification_receiver_emails</code> (array of strings, optional): A list of email addresses to which a notification will be sent after processing finishes.</p>\n</li>\n<li><p><code>skip_reconciliation</code> (boolean, optional): Controls whether to skip the reclassification of the term type (potential switch between Standard and Non-Standard) after processing all batches. By default the reconciliation is on, but it could result in outgrowing the context window, in such case you can set it to <code>true</code> to skip this processing step. <strong>Default</strong>: <code>false</code></p>\n</li>\n<li><p><code>skip_term_type_reconciliation</code> (boolean, optional): Controls whether to skip term type reconciliation specifically. Default: <code>true</code></p>\n</li>\n<li><p><code>skip_cache</code> (boolean, optional): Controls whether to skip cached term extractions. Term extractions are cached in batches, if anything in the batch changes (contracts content, batch size, prompt on Notion) then it will automatically skip the cache and regenerate. Only use this option if you explicilty want to retry extraction without any other changes. <strong>Default</strong>: <code>false</code></p>\n</li>\n<li><p><code>folder_handling_mode</code> (enum, \"all_pdfs\" | \"newest_only\"): Applicable in-case of source containing folders with multiple contracts as a URL.</p>\n<ul>\n<li><p>\"all_pdfs\" forces the system to convert and process all pdfs in a contract and consider them when extracting terms</p>\n</li>\n<li><p>\"newest_only\" considers only the newest document within each folder.</p>\n</li>\n</ul>\n</li>\n<li><p><code>force_reprocess_pdfs</code> (boolden, optional): Allows skipping pdf conversion cache for contract pdfs. <strong>Default</strong>: <code>false</code></p>\n</li>\n<li><p><code>process_each_file_in_folder_individually</code> (boolean, optional): Controls grouping behavior for files from folders.</p>\n<ul>\n<li><p><code>false (default)</code>: Files from the same folder are grouped together for canonical reconciliation (identifies master agreements and related amendments)</p>\n</li>\n<li><p><code>true</code>: Each file is treated as independent with no cross-file grouping. Enables post-expansion chunking for large folders when combined with chunk_contracts.</p>\n</li>\n</ul>\n</li>\n<li><p><code>attempt_dedup_across_input_lines</code> (boolean, optional): Controls cross-input merging behavior.</p>\n<ul>\n<li><p>false (default): Each input line is treated as distinct, no merging across different input URLs</p>\n</li>\n<li><p>true: Files may be merged across input lines if they share the same parent folder (legacy behavior)</p>\n</li>\n</ul>\n</li>\n<li><p><code>chunk_contracts (int, optional)</code> Splits processing into multiple parallel state machine executions. When combined with process_each_file_in_folder_individually: true, chunking occurs after folder expansion, allowing large folders to be processed without hitting size limits. Default: no chunking</p>\n</li>\n<li><p><code>max_folder_groups_per_chunk (int, optional)</code> Controls the maximum number of folder groups processed per state machine execution. When folder groups exceed this limit, processing is automatically split into multiple sequential state machine executions.</p>\n<ul>\n<li><p>Lower values reduce memory pressure and timeout risk for complex folders with many PDFs</p>\n</li>\n<li><p>Higher values result in fewer executions and faster completion for simpler folders<br />  Default: 50 (from DEFAULT_CHUNK_SIZE runtime config)</p>\n</li>\n</ul>\n</li>\n<li><p><code>prompt_label (string, optional)</code> Langfuse prompt label to use for extraction prompts. Falls back to \"production\" if the specified label is not found. Default: <code>production</code></p>\n</li>\n<li><p><code>arr_as_of (Date YYYY-MM-DD, optional)</code> The date from which the ARR for yearly price increase should be considered. Any ARR values prior to this date will not affect the yearly price increase.</p>\n</li>\n<li><p><code>llm_for_extraction</code> (string, optional) LLM model to use for term extraction. Default: \"gemini-3-pro-preview\"</p>\n</li>\n<li><p><code>llm_for_reconciliation</code> (string, optional): LLM model to use for reconciliation steps. Default: \"claude-4-5-sonnet\"</p>\n</li>\n</ul>\n<p>Note that either <code>source</code> or <code>contracts</code> is required.</p>\n<h2 id=\"results\">Results</h2>\n<p>The processing can take quite long (depending on the number of contracts this can be around an hour or even longer) and it will happen in the background. The only thing returned is a step function execution ARN where the processing can be tracked.</p>\n<p>Once processing finishes an email will be sent to the addresses given in <code>notification_receiver_emails</code> together with a donwload link for the results and a summary CSV file listing the key details for each contract</p>\n","urlObject":{"protocol":"https","path":["extract","contracts"],"host":["productmind.trilogy.com"],"query":[],"variable":[]}},"response":[{"id":"b69bc396-a4ad-4447-9d48-2ef940ad6193","name":"Google sheet source","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"company\": \"tivian\",\n  \"source\": {\n    \"url\": \"https://docs.google.com/spreadsheets/d/1S--UEUPpNBpaPmap-0-X4jQpfo93waWgTdrWB-jXqOY/edit?gid=1510430598#gid=1510430598\",\n    \"document_column_name\": \"Contract Document Link\",\n    \"sheet_name\": \"FIN_8 - Customer Contracts\",\n    \"filters\": [\n      {\n        \"column\": \"Contract End Date\",\n        \"operator\": \">=\",\n        \"value\": \"2024-07-01\"\n      }\n    ]\n  },\n  \"notification_receiver_emails\": [\"akos.orban@trilogy.com\"]\n}","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/extract/contracts"},"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json","description":"","type":"text"}],"cookie":[],"responseTime":null,"body":"{\n    \"message\": \"Contract analysis started\",\n    \"execution_arn\": \"arn:aws:states:us-east-1:992382370892:execution:q-productmind-backend-pr127-contractAnalysis:d5f75fa3-d0e7-44bb-91ba-4fa89f6a817f\"\n}"},{"id":"2c706705-747a-4d1b-bbfe-b5d7675cc61d","name":"Contract list in JSON","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"company\": \"cloudsense\",\n  \"contracts\": [\n     \"https://drive.google.com/file/d/16eVHNAwqgB4J45yKp2SvxwuzhuSFPAXV/view?usp=drive_link\",\n     \"https://drive.google.com/file/d/19daKao-zMeGu0sQdJqABvLfCCtWQVX51/view?usp=drive_link\",\n     \"https://drive.google.com/file/d/1paUCPTGUHl7o6tXnaA40GBmaaGf8z1MU/view?usp=drive_link\"\n  ],\n  \"notification_receiver_emails\": [\"akos.orban@trilogy.com\"]\n}","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/extract/contracts"},"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json","description":"","type":"text"}],"cookie":[],"responseTime":null,"body":"{\n    \"message\": \"Contract analysis started\",\n    \"execution_arn\": \"arn:aws:states:us-east-1:992382370892:execution:q-productmind-backend-pr127-contractAnalysis:d5f75fa3-d0e7-44bb-91ba-4fa89f6a817f\"\n}"},{"id":"5fdfacba-19fc-4139-bcc7-def4a05bd814","name":"Extract details from contracts - o3-mini","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"company\": \"tivian\",\n    \"contracts\": [\n        \"https://drive.google.com/drive/folders/1dOe1z0zD_vBxkIblVV1pxpSAf7iRVJJv?usp=sharing\"\n    ],\n    \"notification_receiver_emails\": [\"akos.orban@trilogy.com\"],\n    \"skip_cache\": false,\n    \"llm_for_extraction\": \"o3-mini-high\"\n}","options":{"raw":{"language":"json"}}},"url":"https://pr170.productmind.trilogy.com/extract/contracts"},"_postman_previewlanguage":null,"header":null,"cookie":[],"responseTime":null,"body":null}],"_postman_id":"46d3604b-0cfb-4f0c-a999-5ead29d192ce"},{"name":"Extract structured data AI-PI (state machine)","id":"78377536-366b-4c93-a28b-02e7efe56ec8","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"https://us-east-1.console.aws.amazon.com/states/home?region=us-east-1#/statemachines/view/arn%3Aaws%3Astates%3Aus-east-1%3A992382370892%3AstateMachine%3Aq-productmind-backend-prod-extractStructuredData?type=standard","description":"<p>Provides a composable component to perform extraction of structured data out of unstructured (markdown) content.</p>\n<h3 id=\"parameters\"><strong>Parameters:</strong></h3>\n<ul>\n<li><p><code>documents</code> (object[], required):</p>\n<ul>\n<li><p><code>name</code> (string, required): Name of the document</p>\n</li>\n<li><p><code>content</code> (string, required): Text contents or an s3 url. Example: <code>s3://productmind-convert-to-md/pdf/3c426da988547f0899bab77513444166_1_full.md</code></p>\n</li>\n<li><p><code>url</code> (string, required): Origin url of the document (for unique reference)</p>\n</li>\n</ul>\n</li>\n<li><p><code>context</code> (object, optional): information to be substituted into the prompts during processing. If a value is an array of objects and has a <code>document_url</code> field the given entry will be mapped as context to the proper document when it's being processed. Example:<br />  <code>{ \"parent_docs\": [{ \"document_url\": \"A.pdf\", \"parent\": \"X\"}]}</code></p>\n</li>\n<li><p><code>config</code> (object, required):</p>\n<ul>\n<li><p><code>prompt_notion_page</code> (string, required): Notion page with the prompt for extracting data. Example: <a href=\"https://www.notion.so/trilogy-enterprises/Structured-data-extraction-prompt-14485e927d318071a056f065cbec67a0\">https://www.notion.so/trilogy-enterprises/Structured-data-extraction-prompt-14485e927d318071a056f065cbec67a0</a></p>\n</li>\n<li><p><code>response_schema_notion_page</code> (string, required): Notion page with a JSON schema of expected data structure. Example: <a href=\"https://www.notion.so/trilogy-enterprises/Structured-data-response-schema-14485e927d318008b721cd6bfb97b61c\">https://www.notion.so/trilogy-enterprises/Structured-data-response-schema-14485e927d318008b721cd6bfb97b61c</a></p>\n</li>\n<li><p><code>batch_size</code> (integer, optional): Number of elements in a batch (min. 1) for processing. Default to 1.</p>\n</li>\n<li><p><code>llm_model</code> (string, optional): LLM model to use for processing. Default to <code>o1-preview</code>. Example: <code>claude-3-5-sonnet</code></p>\n</li>\n<li><p><code>skip_cache</code> (boolean, optional): Processing results are normally cached by batches. If you want to bypass this set this field to true.</p>\n</li>\n<li><p><code>output_format</code> (string, required): <code>csv</code> or <code>json</code></p>\n</li>\n</ul>\n</li>\n</ul>\n<p><em>Note</em>: Currently exposed only as a composable state machine. Url refers to the AWS console of the state machine.</p>\n","urlObject":{"protocol":"https","path":["states","home"],"hash":"/statemachines/view/arn%3Aaws%3Astates%3Aus-east-1%3A992382370892%3AstateMachine%3Aq-productmind-backend-prod-extractStructuredData?type=standard","host":["us-east-1","console","aws","amazon","com"],"query":[{"key":"region","value":"us-east-1"}],"variable":[]}},"response":[],"_postman_id":"78377536-366b-4c93-a28b-02e7efe56ec8"},{"name":"Contracts Gap Analysis Kickoff","id":"eca2adf9-848a-4d96-8752-e9f3fd2d8009","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"company\": \"voltcontracts\",\n  \"input_url\": \"https://docs.google.com/document/d/1bpip1zQR3tFYvukO4EO7SBE7teFCzsgPtOzJN-j_ccs/edit?tab=t.0\",\n  \"output_folder_url\": \"https://drive.google.com/drive/folders/188K5lRO42VxGXSzRI_6xpulQj312aYnh?usp=sharing\",\n  \"output_sheet_url\": \"https://docs.google.com/spreadsheets/d/1QnoqlNCSsToBbHjlU05TkKHVuoloVLKaILa5mSr7Dfs/edit?usp=sharing\",\n  \"llm_model\": \"gpt-5.1-extended-thinking\",\n  \"results_limit\": 15,\n  \"notification_emails\": [\"muhammad.ishaq@trilogy.com\"]\n}","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/contracts-gap-analysis","description":"<p>Performs gap analysis between a contract listing document and files stored in ProductMind. Identifies which contracts from the listing have matching documents in the knowledge base and which are missing (gaps).</p>\n<h2 id=\"parameters\">Parameters</h2>\n<ul>\n<li><p>company (string, required): Name of the company/knowledge base to search in ProductMind (e.g., \"voltcontracts\")</p>\n</li>\n<li><p>input_url (string, required): URL of the Google Doc containing the contract listing to analyze. The document should contain a structured list of contracts with counterparty names, dates, and contract identifiers.</p>\n</li>\n<li><p>output_folder_url (string, optional): URL of the Google Drive folder where a new output CSV file will be created. Required if output_sheet_url is not provided.</p>\n</li>\n<li><p>output_sheet_url (string, optional): URL of an existing Google Sheet to append results to. Required if output_folder_url is not provided.</p>\n</li>\n<li><p>notification_emails (array of strings, optional): A list of email addresses to which a notification will be sent after processing finishes. Default: [\"<a href=\"mailto:bogdan.tenea@trilogy.com\">bogdan.tenea@trilogy.com</a>\", \"<a href=\"https://mailto:muhammad.ishaq@trilogy.com\">muhammad.ishaq@trilogy.com</a>\"]</p>\n</li>\n<li><p>llm_model (string, optional): The LLM model to use for contract extraction and matching. Default: \"claude-4-5-sonnet\"</p>\n</li>\n<li><p>results_limit (integer, optional): Maximum number of ProductMind search results to retrieve per counterparty. Higher values may improve matching accuracy but increase processing time and cost. Default: 15</p>\n</li>\n</ul>\n<p>Note: Either output_folder_url or output_sheet_url must be provided.</p>\n<h2 id=\"results\">Results</h2>\n<p>The processing happens asynchronously in the background. The API immediately returns a Step Functions execution ARN where progress can be tracked.The process:</p>\n<ol>\n<li><p>Converts the input Google Doc to markdown</p>\n</li>\n<li><p>Extracts unique contracts and counterparties using LLM</p>\n</li>\n<li><p>Searches ProductMind for each counterparty</p>\n</li>\n<li><p>Matches found files to contract listings using LLM</p>\n</li>\n<li><p>Outputs results to Google Sheet with columns: counterparty, date, number, full_text_id, source, url</p>\n</li>\n</ol>\n<p>Once processing finishes, an email notification is sent to the specified addresses with a summary of matched contracts and gaps.</p>\n","urlObject":{"protocol":"https","path":["contracts-gap-analysis"],"host":["productmind.trilogy.com"],"query":[],"variable":[]}},"response":[],"_postman_id":"eca2adf9-848a-4d96-8752-e9f3fd2d8009"}],"id":"aa3a7499-2b08-4211-ae00-001c4931042b","description":"<p>This folder contains endpoints for <strong>extracting entities from videos to Markdown format</strong>.</p>\n","_postman_id":"aa3a7499-2b08-4211-ae00-001c4931042b"},{"name":"Verify","item":[{"name":"Verify content","id":"265920b2-c239-4598-b832-adf40fff59ab","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"inputs\": [\n        {\"url\": \"https://docs.google.com/spreadsheets/d/1cQETUjyExe1p6CHD7H2M-UMERK_dDMDw4Gmr5vbuM7A/edit?usp=drive_link\", \"name\": \"contract terms\" }\n    ],\n    \"company\": \"cloudsense\",\n    \"evaluation_subject_url\": \"https://docs.google.com/spreadsheets/d/1Rioysx249qRmNB7WtvxrvuznyU7TWOFeasQPtGsD4tY/edit?usp=drive_link\",\n    \"goals\": \"Ensure that the extracted contract terms are matching the gold standard (Subject of evaluation)\",\n    \"prompts\": {\n        \"verify_content\": \"https://www.notion.so/trilogy-enterprises/Generic-verify-content-prompt-15885e927d3180b9a8b9d5ffc3077600\"\n    }\n}\n","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/verify/content","description":"<p>This endpoint is used to verify that some content(s) is matching a set of validation criteria (e.g. jira demo video fulfills the acceptance tests, some extracted markdown text matches a set of rules). The request body should contain a JSON object with the following parameters:</p>\n<ul>\n<li><p>inputs: An array of objects containing the content that will be evaluated. Content can be passed either as a URL or as text (either <code>url</code> or <code>content</code> is required):</p>\n<ul>\n<li><p>url (string): an URL that ProductMind can convert to markdown (all supported formats by /convert/url endpoint)</p>\n</li>\n<li><p>content (string): content passed just as text (can be plain text, markdown, json, yaml, etc. - anything an LLM can understand)</p>\n</li>\n<li><p>name (string, optional): an optional name to identify the content, this will appear in the source field in the output</p>\n</li>\n</ul>\n</li>\n<li><p>company (reqiuired): The name of the company associated with the content verification. Product context will be fetched for this company.</p>\n</li>\n<li><p>product (optional): An optional product that would be used in the query to fetch product context.</p>\n</li>\n<li><p>context (optional): Optional text context that can be useful during evaluation. (e.g. Jira ticket description)</p>\n</li>\n<li><p>evaluation_subject: What should be verified, in a text form. Either <code>evaluation_subject</code> or <code>evaluation_subject_url</code> is required.</p>\n</li>\n<li><p>evaluation_subject_url: What should be verified, as a url that ProducMind can convert to markdown (e.g. a Notion page). Either <code>evaluation_subject</code> or <code>evaluation_subject_url</code> is required.</p>\n</li>\n<li><p>goals (optional): The goals or objectives for ensuring the extracted content meets specific criteria.</p>\n</li>\n<li><p>additional_instructions (optional): Additional rules to give the LLM during verification.</p>\n</li>\n<li><p>reasoning_effort (string, optional): The reasoning_effort parameter for o1 when doing the first round of evaluation. Default: \"medium\". Keep in mind that using \"high\" can make the task run significantly longer, use it when you really need it.</p>\n</li>\n<li><p>prompts (object of strings): Optional override to one or more of the prompts used:</p>\n<ul>\n<li><p>verify_content: Used for first step of verification. Default: <a href=\"https://www.notion.so/trilogy-enterprises/Generic-verify-content-prompt-15885e927d3180b9a8b9d5ffc3077600\">https://www.notion.so/trilogy-enterprises/Generic-verify-content-prompt-15885e927d3180b9a8b9d5ffc3077600</a></p>\n</li>\n<li><p>verify_content_multi_modal: Used when there is no textual input available (e.g. only a video without speech). Default: <a href=\"https://www.notion.so/trilogy-enterprises/Generic-verify-multi-modal-prompt-15d85e927d31802b909dee606f4e982b\">https://www.notion.so/trilogy-enterprises/Generic-verify-multi-modal-prompt-15d85e927d31802b909dee606f4e982b</a></p>\n</li>\n<li><p>product_mind_query: Used to prepare a query for ProductMind to get product context. Default: <a href=\"https://www.notion.so/trilogy-enterprises/ProductMind-query-prompt-13685e927d318091b9d1d38bf4f7c26e\">https://www.notion.so/trilogy-enterprises/ProductMind-query-prompt-13685e927d318091b9d1d38bf4f7c26e</a></p>\n</li>\n<li><p>answer_questions: Used with the rich content (if any) after the verification step. It validates any open questions. Default: <a href=\"https://www.notion.so/trilogy-enterprises/Generic-review-answer-questions-prompt-15d85e927d3180919074f8e4cdbd5da1\">https://www.notion.so/trilogy-enterprises/Generic-review-answer-questions-prompt-15d85e927d3180919074f8e4cdbd5da1</a></p>\n</li>\n</ul>\n</li>\n</ul>\n<p>The response to this request will have a status code of 200 and a content type of application/json. The response body will contain a JSON object with the following parameters:</p>\n<ul>\n<li><p>summary: A brief description of the validation</p>\n</li>\n<li><p>is_whole_subject_covered (boolean): Indicates that there were only \"ok\", \"incomplete\" or \"skipped\" results</p>\n</li>\n<li><p>is_whole_subject_covered_perfectly (boolean): Indicates that there were only \"ok\" results</p>\n</li>\n<li><p>did_all_covered_entries_succeed (boolean): Indicates that there were no \"failed\" cases.</p>\n</li>\n<li><p>detailed_report: An array of objects containing the results for each case:</p>\n<ul>\n<li><p>entry: The name/description of the test case</p>\n</li>\n<li><p>result: The outcome. One of: \"ok\", \"missing\", \"skipped\", \"incomplete\", \"failed\"</p>\n</li>\n<li><p>summary: A description of how the given case is convered (or what would is missing)</p>\n</li>\n<li><p>source: The name of the input which covers the case</p>\n</li>\n</ul>\n</li>\n</ul>\n","urlObject":{"protocol":"https","path":["verify","content"],"host":["productmind.trilogy.com"],"query":[],"variable":[]}},"response":[{"id":"febcfd2c-fcc8-49f1-a758-3624b64dd260","name":"Verify AI image extraction details","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"inputs\": [\n        {\"url\": \"https://docs.google.com/spreadsheets/d/1cQETUjyExe1p6CHD7H2M-UMERK_dDMDw4Gmr5vbuM7A/edit?usp=drive_link\", \"name\": \"contract terms\" }\n    ],\n    \"company\": \"cloudsense\",\n    \"evaluation_subject_url\": \"https://docs.google.com/spreadsheets/d/1Rioysx249qRmNB7WtvxrvuznyU7TWOFeasQPtGsD4tY/edit?usp=drive_link\",\n    \"goals\": \"Ensure that the extracted contract terms are matching the gold standard (Subject of evaluation)\",\n    \"prompts\": {\n        \"verify_content\": \"https://www.notion.so/trilogy-enterprises/Generic-verify-content-prompt-15885e927d3180b9a8b9d5ffc3077600\"\n    }\n}\n","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/verify/content"},"_postman_previewlanguage":null,"header":null,"cookie":[],"responseTime":null,"body":null},{"id":"2108d653-d2a1-419b-bc54-d172f8dcffb5","name":"Verify contract correctness","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"inputs\": [\n        {\"url\": \"https://docs.google.com/spreadsheets/d/1cQETUjyExe1p6CHD7H2M-UMERK_dDMDw4Gmr5vbuM7A/edit?usp=drive_link\", \"name\": \"contract terms\" }\n    ],\n    \"company\": \"cloudsense\",\n    \"evaluation_subject_url\": \"https://docs.google.com/spreadsheets/d/1Rioysx249qRmNB7WtvxrvuznyU7TWOFeasQPtGsD4tY/edit?usp=drive_link\",\n    \"goals\": \"Ensure that the extracted contract terms are matching the gold standard (Subject of evaluation)\",\n    \"prompts\": {\n        \"verify_content\": \"https://www.notion.so/trilogy-enterprises/Generic-verify-content-prompt-15885e927d3180b9a8b9d5ffc3077600\"\n    }\n}\n","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/verify/content"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Date","value":"Tue, 02 Sep 2025 13:32:36 GMT"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"Content-Length","value":"12342"},{"key":"Connection","value":"keep-alive"},{"key":"x-amzn-RequestId","value":"08a78f01-81a4-4f56-9baf-f7c44cd4dce3"},{"key":"x-amz-apigw-id","value":"QRqepE8koAMEdBA="},{"key":"X-Amzn-Trace-Id","value":"Root=1-68b6f12a-085fb40f56870e8e4fda1cb8;Sampled=1;Lineage=1:cbdade84:0"}],"cookie":[],"responseTime":null,"body":"{\n    \"summary\": \"Most of the terms match accurately. However, there are discrepancies with the signing date, the signer's title, and the Contract Law State. All other items align with the gold standard.\",\n    \"detailed_report\": [\n        {\n            \"entry\": \"General | Entity\",\n            \"result\": \"ok\",\n            \"summary\": \"Matches exactly: 'Cloudsense Pty Ltd'.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Does the actual contract document confirm 'Cloudsense Pty Ltd' as the contracting entity in all places?\"\n        },\n        {\n            \"entry\": \"General | Duration\",\n            \"result\": \"ok\",\n            \"summary\": \"Matches exactly with value '84'.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Does the contract text or schedule explicitly show an 84-month total duration?\"\n        },\n        {\n            \"entry\": \"General | Period Start\",\n            \"result\": \"ok\",\n            \"summary\": \"Matches exactly with value '2016-04-30 00:00:00'.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Does the signed agreement text specify this start date in the same format?\"\n        },\n        {\n            \"entry\": \"General | Period End\",\n            \"result\": \"ok\",\n            \"summary\": \"Matches exactly with value '2023-04-30 00:00:00'.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Is there any annex or exhibit specifying the original end date or extension date differently?\"\n        },\n        {\n            \"entry\": \"General | Total Value\",\n            \"result\": \"ok\",\n            \"summary\": \"Matches exactly with value '1788000'.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Does the contract detail how the total of $1,788,000 was calculated or broken down?\"\n        },\n        {\n            \"entry\": \"Signing | Signed Date\",\n            \"result\": \"failed\",\n            \"summary\": \"Mismatch between gold standard '2022-04-29 00:00:00' and content '2022-05-03 00:00:00'.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Does the separate signature certificate or the final signature page show 2022-04-29 or 2022-05-03 as the binding signature date?\"\n        },\n        {\n            \"entry\": \"Signing | Signed By\",\n            \"result\": \"failed\",\n            \"summary\": \"Mismatch between gold standard 'Andrew Griffin, Procurement Category Lead' and content 'Andrew Griffin, Procurement Chapter Lead'.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Does the contract signature block or appended signatory page list 'Category Lead' or 'Chapter Lead' as the correct title?\"\n        },\n        {\n            \"entry\": \"Governing Law | Contract Law Country\",\n            \"result\": \"ok\",\n            \"summary\": \"Matches exactly: 'Australia'.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Does the contract specify 'Australia' clearly for the applicable governing law, or only mention a specific Australian state?\"\n        },\n        {\n            \"entry\": \"Governing Law | Contract Law State\",\n            \"result\": \"incomplete\",\n            \"summary\": \"Gold standard is blank but the content states 'New South Wales'. There's a discrepancy in state-level detail.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Is there a specific clause or section of the contract referencing the State of New South Wales?\"\n        },\n        {\n            \"entry\": \"Governing Law | Dispute Jurisdiction\",\n            \"result\": \"ok\",\n            \"summary\": \"Matches: 'Australia, New South Wales'.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Does the dispute resolution clause explicitly name the courts of New South Wales?\"\n        },\n        {\n            \"entry\": \"Limitation of Liability | Indemnifiable Losses Liability Limit\",\n            \"result\": \"ok\",\n            \"summary\": \"Both show no specified limit (blank in gold standard, no limit in content).\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Does the contract text or schedule truly omit any mention of indemnifiable losses limit?\"\n        },\n        {\n            \"entry\": \"Limitation of Liability | Indemnifiable Losses Liability Limit Monetary Value\",\n            \"result\": \"ok\",\n            \"summary\": \"Both show blank value and no mention.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Does the final agreement or any rider define any monetary cap for indemnifiable losses?\"\n        },\n        {\n            \"entry\": \"Limitation of Liability | IPR Indemnifiable Losses Liability Limit Monetary Value\",\n            \"result\": \"ok\",\n            \"summary\": \"Both show blank and no mention.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Is there any schedule or clause that addresses IP infringement liability differently?\"\n        },\n        {\n            \"entry\": \"Limitation of Liability | Limitation Even If Notified\",\n            \"result\": \"ok\",\n            \"summary\": \"Both are blank and unsaid in the content, so no mismatch.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Is there any broader 'no liability even if notified' language in appended T&Cs?\"\n        },\n        {\n            \"entry\": \"Limitation of Liability | Exclusion of Limitation of Liability\",\n            \"result\": \"ok\",\n            \"summary\": \"Matches: 'No'.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Does the text confirm that no specific exclusions to limitation of liability are included beyond standard terms?\"\n        },\n        {\n            \"entry\": \"Limitation of Liability | Non-Standard Indirect Damages Disclaimer\",\n            \"result\": \"ok\",\n            \"summary\": \"Both show no special disclaimer for indirect damages.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Does the final contract text disclaim consequential or indirect damages in standard language?\"\n        },\n        {\n            \"entry\": \"Auto-Renewal | Auto-Renewal Clause\",\n            \"result\": \"ok\",\n            \"summary\": \"Matches: 'False'.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Is there absolutely no mention of renewal triggers in any schedule or side letter?\"\n        },\n        {\n            \"entry\": \"Auto-Renewal | Auto-Renewal Price\",\n            \"result\": \"ok\",\n            \"summary\": \"Matches: both are blank with no mention.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Could the master agreement or an addendum specify renewal pricing that was not extracted?\"\n        },\n        {\n            \"entry\": \"Auto-Renewal | Auto-Renewal New Duration\",\n            \"result\": \"ok\",\n            \"summary\": \"Matches: both blank and no mention in content.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Is there a hidden schedule that might define new renewal terms beyond the initial 84 months?\"\n        },\n        {\n            \"entry\": \"Auto-Renewal | Auto-Renewal Provider Required Notice Period\",\n            \"result\": \"ok\",\n            \"summary\": \"Matches: both blank, no auto-renewal notice requirements found.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Does the contract or any addendum require any notice from the provider for an extension or renewal?\"\n        },\n        {\n            \"entry\": \"Auto-Renewal | Provider Auto-Renewal Notice Requirements\",\n            \"result\": \"ok\",\n            \"summary\": \"Both blank, no mention.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Is there any reference in the operational manual or policy document about auto-renewal notifications?\"\n        },\n        {\n            \"entry\": \"Pricing & Revenue | Caps on Renewal Price\",\n            \"result\": \"ok\",\n            \"summary\": \"Both indicate no cap is mentioned.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Could an SOW or side letter contain a separate cap for future renewals?\"\n        },\n        {\n            \"entry\": \"Pricing & Revenue | Caps on Renewal Price Amount\",\n            \"result\": \"ok\",\n            \"summary\": \"Both show blank. No mention found in the agreement.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Any separate price control mechanism in a commercial schedule or footnote?\"\n        },\n        {\n            \"entry\": \"Pricing & Revenue | Renewal Price Cap Minimum Period Condition\",\n            \"result\": \"ok\",\n            \"summary\": \"Matches: both blank.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Is there any mention of a multi-year term condition that might serve as a price cap indirectly?\"\n        },\n        {\n            \"entry\": \"Pricing & Revenue | Renewal Price Cap Minimum Spend Condition\",\n            \"result\": \"ok\",\n            \"summary\": \"Matches: both blank, no mention.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Does any add-on or volume discount arrangement serve as a minimum spend condition?\"\n        },\n        {\n            \"entry\": \"Pricing & Revenue | Customer Right to Reduce Entitlements\",\n            \"result\": \"ok\",\n            \"summary\": \"Matches: 'At Renewal'.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Does the contract text explicitly say that entitlements can only be changed upon renewal?\"\n        },\n        {\n            \"entry\": \"Pricing & Revenue | Provider Price Change Notice Period\",\n            \"result\": \"ok\",\n            \"summary\": \"Both show blank, no mention in content.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Does the final contract or a policy require a prior written notice for price changes?\"\n        },\n        {\n            \"entry\": \"Assignment to 3rd Parties | Provider Rights to Use Affiliates/Subcontractors\",\n            \"result\": \"ok\",\n            \"summary\": \"Matches: 'Unrestricted'.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Does the contract mention any disclaimers or obligations about subcontractor performance or liability?\"\n        },\n        {\n            \"entry\": \"Assignment to 3rd Parties | Use of Foreign Entities\",\n            \"result\": \"ok\",\n            \"summary\": \"Matches: 'Allowed'.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Does the contract specify any data sovereignty or security constraints for foreign affiliates?\"\n        },\n        {\n            \"entry\": \"Termination | Customer Non-Renewal Notice Period\",\n            \"result\": \"ok\",\n            \"summary\": \"Both are blank, no mention of a specific notice period.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Is there a main service agreement or master contract that might mention a specific notice period for non-renewal?\"\n        },\n        {\n            \"entry\": \"Termination | Customer Termination at Convenience\",\n            \"result\": \"ok\",\n            \"summary\": \"Matches: 'False'.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Does the contract disclaim any route for Telstra to terminate for convenience aside from normal end-of-term?\"\n        },\n        {\n            \"entry\": \"Termination | Customer Termination at Change of Control\",\n            \"result\": \"ok\",\n            \"summary\": \"Matches: 'False' (no mention).\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Does any cross-reference within the contract speak to M&A or change-of-control scenarios?\"\n        },\n        {\n            \"entry\": \"Termination | Customer Termination for Cause\",\n            \"result\": \"ok\",\n            \"summary\": \"Matches: 'False' (no explicit for-cause mention).\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Is the typical 'breach of contract' or 'insolvency' termination right omitted or is it standard in some separate general T&Cs?\"\n        },\n        {\n            \"entry\": \"Termination | Customer Early Termination Prepaid Fees Refund\",\n            \"result\": \"ok\",\n            \"summary\": \"Matches: 'False', no mention of refunds.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Would partial refunds for prepaid fees be handled in a separate schedule or invoice terms?\"\n        },\n        {\n            \"entry\": \"Termination | Customer Early Termination Remaining Fees Refund\",\n            \"result\": \"ok\",\n            \"summary\": \"Matches: 'False', no mention of refunds.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Is there a possibility that the provider's standard contract template includes a no-refund policy by default?\"\n        },\n        {\n            \"entry\": \"Termination | Provider Right Not to Renew\",\n            \"result\": \"ok\",\n            \"summary\": \"Matches: 'True'.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Is there a clause stating the provider may choose not to renew at its sole discretion?\"\n        },\n        {\n            \"entry\": \"Termination | Provider Lock-in Period\",\n            \"result\": \"ok\",\n            \"summary\": \"Matches: 'False'.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Is there any separate or hidden mention that might create a lock-in beyond the stated term?\"\n        },\n        {\n            \"entry\": \"Termination | Provider Non-Renewal Notice Period\",\n            \"result\": \"ok\",\n            \"summary\": \"Matches: 'No', no specific mention.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Does the final text require the provider to give any notice if they decide not to renew?\"\n        },\n        {\n            \"entry\": \"Termination | Provider Non-Renewal Notice Requirements\",\n            \"result\": \"ok\",\n            \"summary\": \"Matches: both blank for specific requirements.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Any chance the contract references an external policy or standard that might impose notice obligations?\"\n        },\n        {\n            \"entry\": \"Entitlement | Enterprise Service Agreement License\",\n            \"result\": \"ok\",\n            \"summary\": \"Matches: $1,788,000 per year exactly.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Is $1,788,000 per year specifically for months 72–84, or is it locked for the entire final year extension?\"\n        },\n        {\n            \"entry\": \"Non-Standard | Escrow Service\",\n            \"result\": \"ok\",\n            \"summary\": \"Gold standard is blank and content does not mention escrow. Both align in providing no escrow detail.\",\n            \"source\": \"run12-Telstra\",\n            \"question_for_further_review\": \"Could there be a separate escrow arrangement not referenced in the main license agreement?\"\n        }\n    ],\n    \"is_whole_subject_covered\": false,\n    \"is_whole_subject_covered_perfectly\": false,\n    \"did_all_covered_entries_succeed\": false\n}"}],"_postman_id":"265920b2-c239-4598-b832-adf40fff59ab"},{"name":"Verify demo video","id":"3f734e87-6307-4031-9137-81c70261e34b","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"inputs\": [\n        {\"url\":\"https://drive.google.com/file/d/1d95CBbqxbsvM5n2vkM8s7-kdruPkmfcz/view?usp=drive_link\", \"name\": \"Demo video\"}\n    ],\n    \"company\": \"productmind\",\n    \"goals\": \"Review that all the acceptance test cases are present in the video and/or output content, either by validating that it works, or by sufficiently reasoning why it is not explicitly validated (e.g. because it's tested by automatic tests). Require explicit reasoning for every skipped test case.\\nIf acceptance test cases are not explicitly defined derive them from the ticket description\",\n    \"evaluation_subject\": \"## Acceptance tests\\n---\\n\\n---\",\n    \"context\": \"## Ticket information\\n         TAI-126: Notion API error resulted in removal of content from productmind\\n\\n### Description\\n---\\nSome documents got soft deleted in the DB and removed from S3 in the result of Notion API responding with 502 errors when we were trying to check in the hourly sync if the pages still exist.\\n\\n# Example error\\n\\n\\n\\n\\n\\nState machine execution: [https://us-east-1.console.aws.amazon.com/states/home?region=us-east-1#/v2/executions/details/arn:aws:states:us-east-1:992382370892:execution:q-productmind-backend-prod-updateCompaniesAndSync:45909f90-8b71-e9c9-163d-e73e8476ddb1_488866f3-2040-e718-1071-19ebbcff4791](https://us-east-1.console.aws.amazon.com/states/home?region=us-east-1#/v2/executions/details/arn:aws:states:us-east-1:992382370892:execution:q-productmind-backend-prod-updateCompaniesAndSync:45909f90-8b71-e9c9-163d-e73e8476ddb1_488866f3-2040-e718-1071-19ebbcff4791)\\n\\nThe example “e3e72b53-83a7-4958-9ed9-5945b8504e76” page was already restored manually, but others can be still broken.\\n\\n# How to fix incorrect state\\n\\n  * Find all soft deleted Notion pages and compare either   * with cloudwatch logs if it was removed or\\n  * with invocations of removeContent lambda ([https://us-east-1.console.aws.amazon.com/lambda/home?region=us-east-1#/functions/q-productmind-backend-prod-removeContent?tab=image](https://us-east-1.console.aws.amazon.com/lambda/home?region=us-east-1#/functions/q-productmind-backend-prod-removeContent?tab=image)) to see if it was removed on purpose by the user (there are only 28 log streams for this, so this might be simpler)\\n  * If there are any that are soft deleted but shouldn’t be then restore them and run the refresh sync for the given company\\n\\n# How to protect from similar error in the future\\n\\nNotion errors should already be handled better, however it should be double checked that we won’t delete any data from productmind just because Notion API returns an error at the moment, we should limit the deletion only to a specific “not found” error.\\n---\\n\\n### High-level plan\\n---\\n1. Fill in RCA\\n2. Fix wrong data\\n- prepare and execute script \\n   - find incorrectly deleted pages (download from event logs the lambda invocations' event received (these are deleted on purpose -> this has the benefit that we can mark them already in preparation for TAI-84))\\n   - mark these as deleted on purpose (as per TAI-84)\\n   - restore all other soft deleted Notion page in DB\\n   - list companies that need to be sync'd again and execute sync for them \\n3. Make sure that error won't happen again\\n- update auto-sync mechanism to only soft-delete a page if notion returned a not found error (not on any other Notion errors like rate limit or API being down)\\n- unit test this by simulating notion errors\\n---\\n\\n### Task breakdown  \\n---\\n-   Plan and Design\\n-   Clarifying Requirements\\n-   Improve AI Investments\\n---\"\n}\n","options":{"raw":{"language":"json"}}},"url":"https://productmind.trilogy.com/verify/content","description":"<p>See the documentation of the \"Verify content\" endpoint.</p>\n","urlObject":{"protocol":"https","path":["verify","content"],"host":["productmind.trilogy.com"],"query":[],"variable":[]}},"response":[],"_postman_id":"3f734e87-6307-4031-9137-81c70261e34b"}],"id":"80ff3228-f8e2-4401-a872-5126d54e8188","_postman_id":"80ff3228-f8e2-4401-a872-5126d54e8188","description":""},{"name":"Bid models","item":[{"name":"Calculate retention","id":"b083c6d0-ff18-4513-8db1-3c532ad00fe4","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"input_urls\": [\"https://docs.google.com/spreadsheets/d/1CgWoGWqCxsHGKBkKTM52MQGzYWuBhxSN/edit?gid=1817948728#gid=1817948728\"],\n    \"company_name\": \"kognitiv\",\n    \"context\": \"\",\n    \"prompt_label\": \"json\",\n    \"llm_model\": \"claude-3-5-sonnet\"\n}","options":{"raw":{"language":"json"}}},"url":"{{bid-model-retention-url}}","description":"<p>Part of <strong>Bid Modelling</strong>.</p>\n<p>This endpoint calculates Retention for building Bid Model.</p>\n<p>Note that for calculating Retention we have found <code>Claude 3.5 Sonnet</code> (default LLM) to work the best currently. It's recommended over other models (even over o1).</p>\n<h4 id=\"request-body\">Request Body</h4>\n<ul>\n<li><p><code>input_urls</code> (array of strings, required): The URLs of the files that should be used as input. It can be any URL that ProductMind can handle. (e.g. excel, csv uploaded to Google Drive). At least 1 input file is required.</p>\n</li>\n<li><p><code>company_name</code> (string, required): The name of the company for which the analysis is done.</p>\n</li>\n<li><p><code>context</code> (string, optiona): Optional additional context that will be passed to the prompts. (e.g. an unusual financial year structure)</p>\n</li>\n<li><p><code>prompt_label</code> (string, optional): The label of the prompt that should be used from LangFuse. When it's missing the production version of the prompt will be used.</p>\n</li>\n<li><p><code>llm_model</code> (string, optional): Which LLM model to use during analysis. Possible values:</p>\n<ul>\n<li><p><code>claude-3-5-sonnet</code> (default)</p>\n</li>\n<li><p><code>gpt-4o</code></p>\n</li>\n<li><p><code>o1</code></p>\n</li>\n</ul>\n</li>\n<li><p><code>model_parameters</code> (object, optional): Optional parameters to the LLM model. For example <code>{ \"reasoning_effort\": \"high\" }</code> for o1, or <code>{\"temperature\": 0.5}</code> for Sonnet</p>\n</li>\n<li><p><code>return_mode</code> (string, optional): Controls how to return the results. Possible values:</p>\n<ul>\n<li><p><code>direct</code> (default): returns JSON</p>\n</li>\n<li><p><code>s3_url</code> : returns an S3 url as a combination of bucket + key to the json file (using this will require access to the S3 bucket)</p>\n</li>\n<li><p><code>s3_presigned_url</code> : returns a presigned S3 url valid for 1h to the json file (doesn't require access to the bucket to download the file)</p>\n</li>\n</ul>\n</li>\n</ul>\n<p>Note that when converting the input url the <code>optimize_for_tool_use</code> option will be used from the Convert endpoint, meaning some Python tool friendly source formats (e.g. Excel, Google Sheet, CSV) will not be converted to markdown, but rather be used as is. Other files will be converted first to markdown.</p>\n<h4 id=\"response\">Response</h4>\n<p>The response to this request will have a status code of 200 and a content type of application/json. The response body will contain the following data:</p>\n<ul>\n<li><p><code>normal_mrr_retention</code> (array): An array of objects containing various retention metrics such as beginning of period (bop), gross adds, upgrade, churn, downgrade, end of period (eop), beginning of period customers, end of period customers, churn percentage, gross dollar retention (gdr), net dollar retention (ndr), customer change, and month.</p>\n</li>\n<li><p><code>average_mrr_retention</code> (array): An array of objects similar to <code>normal_mrr_retention</code> containing average retention metrics.</p>\n</li>\n<li><p><code>conclusions</code> (text): Any conclusions or additional information resulting from the retention data analysis.</p>\n</li>\n</ul>\n","urlObject":{"host":["{{bid-model-retention-url}}"],"query":[],"variable":[]}},"response":[{"id":"98505f78-3bb4-408b-ab14-e9589840a61f","name":"Calculate retention","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"input_urls\": [\"https://docs.google.com/spreadsheets/d/1bPZJEzSxU1_jmDm8rdTKD8UwUdJdQz3I_S81azzVQEQ/edit?usp=sharing\"],\n    \"company_name\": \"Gimmal\",\n    \"context\": \"n.a.\",\n    \"prompt_label\": \"multi-year-retention\"\n}","options":{"raw":{"language":"json"}}},"url":"{{bid-model-retention-url}}"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Date","value":"Thu, 30 Jan 2025 09:33:22 GMT"},{"key":"Content-Type","value":"application/json"},{"key":"Content-Length","value":"49559"},{"key":"Connection","value":"keep-alive"},{"key":"x-amzn-RequestId","value":"d9970b0f-4a05-4081-b27b-55d047656d28"},{"key":"X-Amzn-Trace-Id","value":"Root=1-679b45ee-319140b9707e6eea4feac54d;Sampled=1;Lineage=1:0d6ac8f5:0"}],"cookie":[],"responseTime":null,"body":"{\n    \"summary\": {\n        \"month\": \"2024 12\",\n        \"avg_mrr_ndr\": 0.9325,\n        \"avg_mrr_gdr\": 0.8443,\n        \"avg_mrr_churn_percent\": -0.1403,\n        \"avg_mrr_customer_change\": 0.8353,\n        \"avg_mrr_24months_ndr\": 0.9325,\n        \"avg_mrr_24months_gdr\": 0.7705,\n        \"avg_mrr_24months_churn_percent\": -0.2079,\n        \"avg_mrr_24months_customer_change\": 0.744,\n        \"avg_mrr_36months_ndr\": 0.7802,\n        \"avg_mrr_36months_gdr\": 0.6401,\n        \"avg_mrr_36months_churn_percent\": -0.3333,\n        \"avg_mrr_36months_customer_change\": 0.6186,\n        \"avg_mrr_48months_ndr\": 0.6633,\n        \"avg_mrr_48months_gdr\": 0.5436,\n        \"avg_mrr_48months_churn_percent\": -0.4334,\n        \"avg_mrr_48months_customer_change\": 0.53,\n        \"avg_mrr_60months_ndr\": 0.5913,\n        \"avg_mrr_60months_gdr\": 0.4935,\n        \"avg_mrr_60months_churn_percent\": -0.4804,\n        \"avg_mrr_60months_customer_change\": 0.4464,\n        \"normal_mrr_ndr\": 0.9523,\n        \"normal_mrr_gdr\": 0.8397,\n        \"normal_mrr_churn_percent\": -0.1388,\n        \"normal_mrr_customer_change\": 0.8353\n    },\n    \"details\": {\n        \"normal_mrr_retention\": [\n            {\n                \"month\": \"2020 12\",\n                \"bop\": 840693.07,\n                \"gross_adds\": 146725.63,\n                \"upgrade\": 49038.5,\n                \"churn\": -89330.15,\n                \"downgrade\": -29502.97,\n                \"eop\": 917624.08,\n                \"bop_customer\": 699,\n                \"eop_customer\": 589,\n                \"churn_percent\": -0.1063,\n                \"gdr\": 0.8586,\n                \"ndr\": 0.917,\n                \"customer_change\": 0.8426\n            },\n            {\n                \"month\": \"2021 01\",\n                \"bop\": 837989.98,\n                \"gross_adds\": 140526.74,\n                \"upgrade\": 45392.09,\n                \"churn\": -92016.81,\n                \"downgrade\": -21235.28,\n                \"eop\": 910656.72,\n                \"bop_customer\": 696,\n                \"eop_customer\": 583,\n                \"churn_percent\": -0.1098,\n                \"gdr\": 0.8649,\n                \"ndr\": 0.919,\n                \"customer_change\": 0.8376\n            },\n            {\n                \"month\": \"2021 02\",\n                \"bop\": 840069.44,\n                \"gross_adds\": 141135.88,\n                \"upgrade\": 44051.07,\n                \"churn\": -89534.61,\n                \"downgrade\": -21370.22,\n                \"eop\": 914351.55,\n                \"bop_customer\": 690,\n                \"eop_customer\": 581,\n                \"churn_percent\": -0.1066,\n                \"gdr\": 0.868,\n                \"ndr\": 0.9204,\n                \"customer_change\": 0.842\n            },\n            {\n                \"month\": \"2021 03\",\n                \"bop\": 849060.86,\n                \"gross_adds\": 139817.83,\n                \"upgrade\": 45031.33,\n                \"churn\": -89118.54,\n                \"downgrade\": -22469.29,\n                \"eop\": 922322.18,\n                \"bop_customer\": 687,\n                \"eop_customer\": 584,\n                \"churn_percent\": -0.105,\n                \"gdr\": 0.8686,\n                \"ndr\": 0.9216,\n                \"customer_change\": 0.8501\n            },\n            {\n                \"month\": \"2021 04\",\n                \"bop\": 836851.22,\n                \"gross_adds\": 144187.21,\n                \"upgrade\": 44219.28,\n                \"churn\": -86067.35,\n                \"downgrade\": -21207.67,\n                \"eop\": 917982.7,\n                \"bop_customer\": 680,\n                \"eop_customer\": 582,\n                \"churn_percent\": -0.1028,\n                \"gdr\": 0.8718,\n                \"ndr\": 0.9247,\n                \"customer_change\": 0.8559\n            },\n            {\n                \"month\": \"2021 05\",\n                \"bop\": 859787.42,\n                \"gross_adds\": 120423.82,\n                \"upgrade\": 48827.53,\n                \"churn\": -92811.69,\n                \"downgrade\": -22256.86,\n                \"eop\": 913970.21,\n                \"bop_customer\": 685,\n                \"eop_customer\": 587,\n                \"churn_percent\": -0.1079,\n                \"gdr\": 0.8662,\n                \"ndr\": 0.923,\n                \"customer_change\": 0.8569\n            },\n            {\n                \"month\": \"2021 06\",\n                \"bop\": 885354.07,\n                \"gross_adds\": 107042.77,\n                \"upgrade\": 50385.11,\n                \"churn\": -113554.9,\n                \"downgrade\": -20186.36,\n                \"eop\": 909040.69,\n                \"bop_customer\": 689,\n                \"eop_customer\": 588,\n                \"churn_percent\": -0.1283,\n                \"gdr\": 0.8489,\n                \"ndr\": 0.9058,\n                \"customer_change\": 0.8534\n            },\n            {\n                \"month\": \"2021 07\",\n                \"bop\": 886428.04,\n                \"gross_adds\": 105376.67,\n                \"upgrade\": 48960.58,\n                \"churn\": -110992.4,\n                \"downgrade\": -20106.6,\n                \"eop\": 909666.29,\n                \"bop_customer\": 685,\n                \"eop_customer\": 588,\n                \"churn_percent\": -0.1252,\n                \"gdr\": 0.8521,\n                \"ndr\": 0.9073,\n                \"customer_change\": 0.8584\n            },\n            {\n                \"month\": \"2021 08\",\n                \"bop\": 888146.94,\n                \"gross_adds\": 99183.62,\n                \"upgrade\": 51076.87,\n                \"churn\": -110519.33,\n                \"downgrade\": -20885.19,\n                \"eop\": 907002.92,\n                \"bop_customer\": 681,\n                \"eop_customer\": 585,\n                \"churn_percent\": -0.1244,\n                \"gdr\": 0.852,\n                \"ndr\": 0.9096,\n                \"customer_change\": 0.859\n            },\n            {\n                \"month\": \"2021 09\",\n                \"bop\": 908587.11,\n                \"gross_adds\": 96245.14,\n                \"upgrade\": 57771.16,\n                \"churn\": -138688.63,\n                \"downgrade\": -18246.44,\n                \"eop\": 905668.35,\n                \"bop_customer\": 680,\n                \"eop_customer\": 580,\n                \"churn_percent\": -0.1526,\n                \"gdr\": 0.8273,\n                \"ndr\": 0.8909,\n                \"customer_change\": 0.8529\n            },\n            {\n                \"month\": \"2021 10\",\n                \"bop\": 905142.11,\n                \"gross_adds\": 84778.7,\n                \"upgrade\": 51350.74,\n                \"churn\": -118568.69,\n                \"downgrade\": -25056.58,\n                \"eop\": 897646.28,\n                \"bop_customer\": 679,\n                \"eop_customer\": 578,\n                \"churn_percent\": -0.131,\n                \"gdr\": 0.8413,\n                \"ndr\": 0.8981,\n                \"customer_change\": 0.8513\n            },\n            {\n                \"month\": \"2021 11\",\n                \"bop\": 918149.91,\n                \"gross_adds\": 81671.32,\n                \"upgrade\": 41499.38,\n                \"churn\": -120786.12,\n                \"downgrade\": -24045.91,\n                \"eop\": 896488.57,\n                \"bop_customer\": 679,\n                \"eop_customer\": 576,\n                \"churn_percent\": -0.1316,\n                \"gdr\": 0.8423,\n                \"ndr\": 0.8875,\n                \"customer_change\": 0.8483\n            },\n            {\n                \"month\": \"2021 12\",\n                \"bop\": 917624.08,\n                \"gross_adds\": 112522.97,\n                \"upgrade\": 46193.87,\n                \"churn\": -125788.28,\n                \"downgrade\": -18398.3,\n                \"eop\": 932154.34,\n                \"bop_customer\": 683,\n                \"eop_customer\": 570,\n                \"churn_percent\": -0.1371,\n                \"gdr\": 0.8429,\n                \"ndr\": 0.8932,\n                \"customer_change\": 0.8346\n            },\n            {\n                \"month\": \"2022 01\",\n                \"bop\": 910656.72,\n                \"gross_adds\": 111602.28,\n                \"upgrade\": 51013,\n                \"churn\": -125904.54,\n                \"downgrade\": -31465.76,\n                \"eop\": 915901.7,\n                \"bop_customer\": 672,\n                \"eop_customer\": 558,\n                \"churn_percent\": -0.1383,\n                \"gdr\": 0.8272,\n                \"ndr\": 0.8832,\n                \"customer_change\": 0.8304\n            },\n            {\n                \"month\": \"2022 02\",\n                \"bop\": 914351.55,\n                \"gross_adds\": 112305.37,\n                \"upgrade\": 50423.81,\n                \"churn\": -127380.66,\n                \"downgrade\": -34270.99,\n                \"eop\": 915429.07,\n                \"bop_customer\": 670,\n                \"eop_customer\": 552,\n                \"churn_percent\": -0.1393,\n                \"gdr\": 0.8232,\n                \"ndr\": 0.8784,\n                \"customer_change\": 0.8239\n            },\n            {\n                \"month\": \"2022 03\",\n                \"bop\": 922322.18,\n                \"gross_adds\": 108255.51,\n                \"upgrade\": 49124.79,\n                \"churn\": -135480.24,\n                \"downgrade\": -33696.38,\n                \"eop\": 910525.86,\n                \"bop_customer\": 671,\n                \"eop_customer\": 554,\n                \"churn_percent\": -0.1469,\n                \"gdr\": 0.8166,\n                \"ndr\": 0.8698,\n                \"customer_change\": 0.8256\n            },\n            {\n                \"month\": \"2022 04\",\n                \"bop\": 917982.7,\n                \"gross_adds\": 108886.75,\n                \"upgrade\": 50210.53,\n                \"churn\": -127481.73,\n                \"downgrade\": -34756.85,\n                \"eop\": 914841.39,\n                \"bop_customer\": 669,\n                \"eop_customer\": 548,\n                \"churn_percent\": -0.1389,\n                \"gdr\": 0.8233,\n                \"ndr\": 0.878,\n                \"customer_change\": 0.8191\n            },\n            {\n                \"month\": \"2022 05\",\n                \"bop\": 913970.21,\n                \"gross_adds\": 108849.38,\n                \"upgrade\": 49247.15,\n                \"churn\": -133410.56,\n                \"downgrade\": -33193.59,\n                \"eop\": 905462.59,\n                \"bop_customer\": 663,\n                \"eop_customer\": 535,\n                \"churn_percent\": -0.146,\n                \"gdr\": 0.8177,\n                \"ndr\": 0.8716,\n                \"customer_change\": 0.8069\n            },\n            {\n                \"month\": \"2022 06\",\n                \"bop\": 909040.69,\n                \"gross_adds\": 99657,\n                \"upgrade\": 65330.04,\n                \"churn\": -123412.1,\n                \"downgrade\": -44077.05,\n                \"eop\": 906538.58,\n                \"bop_customer\": 665,\n                \"eop_customer\": 536,\n                \"churn_percent\": -0.1358,\n                \"gdr\": 0.8158,\n                \"ndr\": 0.8876,\n                \"customer_change\": 0.806\n            },\n            {\n                \"month\": \"2022 07\",\n                \"bop\": 909666.29,\n                \"gross_adds\": 91832,\n                \"upgrade\": 70793.57,\n                \"churn\": -118996.34,\n                \"downgrade\": -43999.15,\n                \"eop\": 909296.38,\n                \"bop_customer\": 660,\n                \"eop_customer\": 531,\n                \"churn_percent\": -0.1308,\n                \"gdr\": 0.8208,\n                \"ndr\": 0.8986,\n                \"customer_change\": 0.8045\n            },\n            {\n                \"month\": \"2022 08\",\n                \"bop\": 907002.92,\n                \"gross_adds\": 89506.66,\n                \"upgrade\": 70603.4,\n                \"churn\": -128857.05,\n                \"downgrade\": -40536.28,\n                \"eop\": 897719.64,\n                \"bop_customer\": 651,\n                \"eop_customer\": 525,\n                \"churn_percent\": -0.1421,\n                \"gdr\": 0.8132,\n                \"ndr\": 0.8911,\n                \"customer_change\": 0.8065\n            },\n            {\n                \"month\": \"2022 09\",\n                \"bop\": 905668.35,\n                \"gross_adds\": 84165.37,\n                \"upgrade\": 69656.76,\n                \"churn\": -106316.65,\n                \"downgrade\": -39278.4,\n                \"eop\": 913895.42,\n                \"bop_customer\": 648,\n                \"eop_customer\": 528,\n                \"churn_percent\": -0.1174,\n                \"gdr\": 0.8392,\n                \"ndr\": 0.9162,\n                \"customer_change\": 0.8148\n            },\n            {\n                \"month\": \"2022 10\",\n                \"bop\": 897646.28,\n                \"gross_adds\": 84498.23,\n                \"upgrade\": 66597.44,\n                \"churn\": -126117.44,\n                \"downgrade\": -39795.83,\n                \"eop\": 882828.68,\n                \"bop_customer\": 638,\n                \"eop_customer\": 522,\n                \"churn_percent\": -0.1405,\n                \"gdr\": 0.8152,\n                \"ndr\": 0.8894,\n                \"customer_change\": 0.8182\n            },\n            {\n                \"month\": \"2022 11\",\n                \"bop\": 896488.57,\n                \"gross_adds\": 89610.62,\n                \"upgrade\": 70340.82,\n                \"churn\": -129116.53,\n                \"downgrade\": -38843.74,\n                \"eop\": 888479.75,\n                \"bop_customer\": 633,\n                \"eop_customer\": 519,\n                \"churn_percent\": -0.144,\n                \"gdr\": 0.8126,\n                \"ndr\": 0.8911,\n                \"customer_change\": 0.8199\n            },\n            {\n                \"month\": \"2022 12\",\n                \"bop\": 932154.34,\n                \"gross_adds\": 54894.52,\n                \"upgrade\": 78394.51,\n                \"churn\": -134636.51,\n                \"downgrade\": -37246.68,\n                \"eop\": 893560.18,\n                \"bop_customer\": 624,\n                \"eop_customer\": 517,\n                \"churn_percent\": -0.1444,\n                \"gdr\": 0.8156,\n                \"ndr\": 0.8997,\n                \"customer_change\": 0.8285\n            },\n            {\n                \"month\": \"2023 01\",\n                \"bop\": 915901.7,\n                \"gross_adds\": 56283.35,\n                \"upgrade\": 79863.92,\n                \"churn\": -130977.85,\n                \"downgrade\": -27870.08,\n                \"eop\": 893201.05,\n                \"bop_customer\": 611,\n                \"eop_customer\": 515,\n                \"churn_percent\": -0.143,\n                \"gdr\": 0.8266,\n                \"ndr\": 0.9138,\n                \"customer_change\": 0.8429\n            },\n            {\n                \"month\": \"2023 02\",\n                \"bop\": 915429.07,\n                \"gross_adds\": 53927.1,\n                \"upgrade\": 78556.73,\n                \"churn\": -133984.24,\n                \"downgrade\": -22236.7,\n                \"eop\": 891691.97,\n                \"bop_customer\": 605,\n                \"eop_customer\": 511,\n                \"churn_percent\": -0.1464,\n                \"gdr\": 0.8293,\n                \"ndr\": 0.9152,\n                \"customer_change\": 0.8446\n            },\n            {\n                \"month\": \"2023 03\",\n                \"bop\": 910525.86,\n                \"gross_adds\": 56857.91,\n                \"upgrade\": 80843.02,\n                \"churn\": -122353.71,\n                \"downgrade\": -21940.59,\n                \"eop\": 903932.49,\n                \"bop_customer\": 604,\n                \"eop_customer\": 512,\n                \"churn_percent\": -0.1344,\n                \"gdr\": 0.8415,\n                \"ndr\": 0.9303,\n                \"customer_change\": 0.8477\n            },\n            {\n                \"month\": \"2023 04\",\n                \"bop\": 914841.39,\n                \"gross_adds\": 46969.89,\n                \"upgrade\": 87432.62,\n                \"churn\": -118195.98,\n                \"downgrade\": -24575.89,\n                \"eop\": 906472.03,\n                \"bop_customer\": 595,\n                \"eop_customer\": 507,\n                \"churn_percent\": -0.1292,\n                \"gdr\": 0.8439,\n                \"ndr\": 0.9395,\n                \"customer_change\": 0.8521\n            },\n            {\n                \"month\": \"2023 05\",\n                \"bop\": 905462.59,\n                \"gross_adds\": 48582.69,\n                \"upgrade\": 90664.55,\n                \"churn\": -117681.21,\n                \"downgrade\": -18211.75,\n                \"eop\": 908816.87,\n                \"bop_customer\": 582,\n                \"eop_customer\": 499,\n                \"churn_percent\": -0.13,\n                \"gdr\": 0.8499,\n                \"ndr\": 0.95,\n                \"customer_change\": 0.8574\n            },\n            {\n                \"month\": \"2023 06\",\n                \"bop\": 906538.58,\n                \"gross_adds\": 48653.6,\n                \"upgrade\": 94181.73,\n                \"churn\": -101579.44,\n                \"downgrade\": -22866.84,\n                \"eop\": 924927.62,\n                \"bop_customer\": 576,\n                \"eop_customer\": 494,\n                \"churn_percent\": -0.1121,\n                \"gdr\": 0.8627,\n                \"ndr\": 0.9666,\n                \"customer_change\": 0.8576\n            },\n            {\n                \"month\": \"2023 07\",\n                \"bop\": 909296.38,\n                \"gross_adds\": 55859.51,\n                \"upgrade\": 95061.82,\n                \"churn\": -117508.46,\n                \"downgrade\": -21999.08,\n                \"eop\": 920710.17,\n                \"bop_customer\": 567,\n                \"eop_customer\": 488,\n                \"churn_percent\": -0.1292,\n                \"gdr\": 0.8466,\n                \"ndr\": 0.9511,\n                \"customer_change\": 0.8607\n            },\n            {\n                \"month\": \"2023 08\",\n                \"bop\": 897719.64,\n                \"gross_adds\": 60682.52,\n                \"upgrade\": 96069.99,\n                \"churn\": -103391,\n                \"downgrade\": -22384.39,\n                \"eop\": 928696.76,\n                \"bop_customer\": 558,\n                \"eop_customer\": 484,\n                \"churn_percent\": -0.1152,\n                \"gdr\": 0.8599,\n                \"ndr\": 0.9669,\n                \"customer_change\": 0.8674\n            },\n            {\n                \"month\": \"2023 09\",\n                \"bop\": 913895.42,\n                \"gross_adds\": 46916.24,\n                \"upgrade\": 106911.82,\n                \"churn\": -100461.84,\n                \"downgrade\": -19953.35,\n                \"eop\": 947308.29,\n                \"bop_customer\": 559,\n                \"eop_customer\": 486,\n                \"churn_percent\": -0.1099,\n                \"gdr\": 0.8682,\n                \"ndr\": 0.9852,\n                \"customer_change\": 0.8694\n            },\n            {\n                \"month\": \"2023 10\",\n                \"bop\": 882828.68,\n                \"gross_adds\": 50474.99,\n                \"upgrade\": 118365.06,\n                \"churn\": -73760.6,\n                \"downgrade\": -16668.12,\n                \"eop\": 961240,\n                \"bop_customer\": 553,\n                \"eop_customer\": 484,\n                \"churn_percent\": -0.0836,\n                \"gdr\": 0.8976,\n                \"ndr\": 1.0316,\n                \"customer_change\": 0.8752\n            },\n            {\n                \"month\": \"2023 11\",\n                \"bop\": 888479.75,\n                \"gross_adds\": 62993.12,\n                \"upgrade\": 113395.46,\n                \"churn\": -80235.58,\n                \"downgrade\": -16952.91,\n                \"eop\": 967679.83,\n                \"bop_customer\": 548,\n                \"eop_customer\": 475,\n                \"churn_percent\": -0.0903,\n                \"gdr\": 0.8906,\n                \"ndr\": 1.0182,\n                \"customer_change\": 0.8668\n            },\n            {\n                \"month\": \"2023 12\",\n                \"bop\": 893560.18,\n                \"gross_adds\": 76677.23,\n                \"upgrade\": 105637.06,\n                \"churn\": -68841,\n                \"downgrade\": -14828.49,\n                \"eop\": 992204.99,\n                \"bop_customer\": 543,\n                \"eop_customer\": 473,\n                \"churn_percent\": -0.077,\n                \"gdr\": 0.9064,\n                \"ndr\": 1.0246,\n                \"customer_change\": 0.8711\n            },\n            {\n                \"month\": \"2024 01\",\n                \"bop\": 893201.05,\n                \"gross_adds\": 76156.11,\n                \"upgrade\": 97767.15,\n                \"churn\": -58885.4,\n                \"downgrade\": -16131.26,\n                \"eop\": 992107.65,\n                \"bop_customer\": 541,\n                \"eop_customer\": 473,\n                \"churn_percent\": -0.0659,\n                \"gdr\": 0.916,\n                \"ndr\": 1.0255,\n                \"customer_change\": 0.8743\n            },\n            {\n                \"month\": \"2024 02\",\n                \"bop\": 891691.97,\n                \"gross_adds\": 79691.51,\n                \"upgrade\": 96583.98,\n                \"churn\": -64584.04,\n                \"downgrade\": -16205.75,\n                \"eop\": 987177.67,\n                \"bop_customer\": 535,\n                \"eop_customer\": 466,\n                \"churn_percent\": -0.0724,\n                \"gdr\": 0.9094,\n                \"ndr\": 1.0177,\n                \"customer_change\": 0.871\n            },\n            {\n                \"month\": \"2024 03\",\n                \"bop\": 903932.49,\n                \"gross_adds\": 94958.6,\n                \"upgrade\": 94754.4,\n                \"churn\": -68799.38,\n                \"downgrade\": -17397.41,\n                \"eop\": 1007448.7,\n                \"bop_customer\": 534,\n                \"eop_customer\": 461,\n                \"churn_percent\": -0.0761,\n                \"gdr\": 0.9046,\n                \"ndr\": 1.0095,\n                \"customer_change\": 0.8633\n            },\n            {\n                \"month\": \"2024 04\",\n                \"bop\": 906472.03,\n                \"gross_adds\": 99125.26,\n                \"upgrade\": 95092.28,\n                \"churn\": -114025.39,\n                \"downgrade\": -15374.09,\n                \"eop\": 971290.09,\n                \"bop_customer\": 527,\n                \"eop_customer\": 447,\n                \"churn_percent\": -0.1258,\n                \"gdr\": 0.8572,\n                \"ndr\": 0.9622,\n                \"customer_change\": 0.8482\n            },\n            {\n                \"month\": \"2024 05\",\n                \"bop\": 908816.87,\n                \"gross_adds\": 99035.96,\n                \"upgrade\": 86833.81,\n                \"churn\": -106858.95,\n                \"downgrade\": -16053.58,\n                \"eop\": 971774.11,\n                \"bop_customer\": 520,\n                \"eop_customer\": 444,\n                \"churn_percent\": -0.1176,\n                \"gdr\": 0.8648,\n                \"ndr\": 0.9603,\n                \"customer_change\": 0.8538\n            },\n            {\n                \"month\": \"2024 06\",\n                \"bop\": 924927.62,\n                \"gross_adds\": 127812.75,\n                \"upgrade\": 81157.47,\n                \"churn\": -117342.55,\n                \"downgrade\": -21274.87,\n                \"eop\": 995280.42,\n                \"bop_customer\": 515,\n                \"eop_customer\": 439,\n                \"churn_percent\": -0.1269,\n                \"gdr\": 0.8501,\n                \"ndr\": 0.9379,\n                \"customer_change\": 0.8524\n            },\n            {\n                \"month\": \"2024 07\",\n                \"bop\": 920710.17,\n                \"gross_adds\": 130090.79,\n                \"upgrade\": 77315.09,\n                \"churn\": -110182.75,\n                \"downgrade\": -20914.58,\n                \"eop\": 997018.72,\n                \"bop_customer\": 511,\n                \"eop_customer\": 435,\n                \"churn_percent\": -0.1197,\n                \"gdr\": 0.8576,\n                \"ndr\": 0.9416,\n                \"customer_change\": 0.8513\n            },\n            {\n                \"month\": \"2024 08\",\n                \"bop\": 928696.76,\n                \"gross_adds\": 125905.28,\n                \"upgrade\": 71081.54,\n                \"churn\": -121204.66,\n                \"downgrade\": -19911.67,\n                \"eop\": 984567.24,\n                \"bop_customer\": 510,\n                \"eop_customer\": 428,\n                \"churn_percent\": -0.1305,\n                \"gdr\": 0.848,\n                \"ndr\": 0.9246,\n                \"customer_change\": 0.8392\n            },\n            {\n                \"month\": \"2024 09\",\n                \"bop\": 947308.29,\n                \"gross_adds\": 120183.75,\n                \"upgrade\": 91114.31,\n                \"churn\": -115363.96,\n                \"downgrade\": -21961.81,\n                \"eop\": 1021280.58,\n                \"bop_customer\": 507,\n                \"eop_customer\": 428,\n                \"churn_percent\": -0.1218,\n                \"gdr\": 0.855,\n                \"ndr\": 0.9512,\n                \"customer_change\": 0.8442\n            },\n            {\n                \"month\": \"2024 10\",\n                \"bop\": 961240,\n                \"gross_adds\": 116587.04,\n                \"upgrade\": 96324,\n                \"churn\": -123252.03,\n                \"downgrade\": -20705.5,\n                \"eop\": 1030193.51,\n                \"bop_customer\": 509,\n                \"eop_customer\": 429,\n                \"churn_percent\": -0.1282,\n                \"gdr\": 0.8502,\n                \"ndr\": 0.9504,\n                \"customer_change\": 0.8428\n            },\n            {\n                \"month\": \"2024 11\",\n                \"bop\": 967679.83,\n                \"gross_adds\": 118398.6,\n                \"upgrade\": 95791.66,\n                \"churn\": -121285.04,\n                \"downgrade\": -21813.36,\n                \"eop\": 1038771.68,\n                \"bop_customer\": 504,\n                \"eop_customer\": 425,\n                \"churn_percent\": -0.1253,\n                \"gdr\": 0.8521,\n                \"ndr\": 0.9511,\n                \"customer_change\": 0.8433\n            },\n            {\n                \"month\": \"2024 12\",\n                \"bop\": 992204.99,\n                \"gross_adds\": 125189.86,\n                \"upgrade\": 111766.43,\n                \"churn\": -137702.99,\n                \"downgrade\": -21358.08,\n                \"eop\": 1070100.2,\n                \"bop_customer\": 504,\n                \"eop_customer\": 421,\n                \"churn_percent\": -0.1388,\n                \"gdr\": 0.8397,\n                \"ndr\": 0.9523,\n                \"customer_change\": 0.8353\n            }\n        ],\n        \"average_mrr_retention\": [\n            {\n                \"month\": \"2020 12\",\n                \"bop\": 840693.07,\n                \"gross_adds\": 144226.53,\n                \"upgrade\": 23963.4,\n                \"churn\": -89330.15,\n                \"downgrade\": -16366.81,\n                \"eop\": 903186.04,\n                \"bop_customer\": 699,\n                \"eop_customer\": 589,\n                \"churn_percent\": -0.1063,\n                \"gdr\": 0.8743,\n                \"ndr\": 0.9028,\n                \"customer_change\": 0.8426\n            },\n            {\n                \"month\": \"2021 01\",\n                \"bop\": 839105.48,\n                \"gross_adds\": 138059.22,\n                \"upgrade\": 23654.11,\n                \"churn\": -91947.9,\n                \"downgrade\": -13198.89,\n                \"eop\": 895672.03,\n                \"bop_customer\": 696,\n                \"eop_customer\": 583,\n                \"churn_percent\": -0.1096,\n                \"gdr\": 0.8747,\n                \"ndr\": 0.9029,\n                \"customer_change\": 0.8376\n            },\n            {\n                \"month\": \"2021 02\",\n                \"bop\": 837810.95,\n                \"gross_adds\": 139143.68,\n                \"upgrade\": 24717.98,\n                \"churn\": -89597.06,\n                \"downgrade\": -13053.11,\n                \"eop\": 899022.45,\n                \"bop_customer\": 690,\n                \"eop_customer\": 581,\n                \"churn_percent\": -0.1069,\n                \"gdr\": 0.8775,\n                \"ndr\": 0.907,\n                \"customer_change\": 0.842\n            },\n            {\n                \"month\": \"2021 03\",\n                \"bop\": 845846.6,\n                \"gross_adds\": 138053.72,\n                \"upgrade\": 26400.77,\n                \"churn\": -89057.29,\n                \"downgrade\": -13532.68,\n                \"eop\": 907711.12,\n                \"bop_customer\": 687,\n                \"eop_customer\": 584,\n                \"churn_percent\": -0.1053,\n                \"gdr\": 0.8787,\n                \"ndr\": 0.9099,\n                \"customer_change\": 0.8501\n            },\n            {\n                \"month\": \"2021 04\",\n                \"bop\": 835178.79,\n                \"gross_adds\": 141843.18,\n                \"upgrade\": 27453.85,\n                \"churn\": -86812.56,\n                \"downgrade\": -13837.27,\n                \"eop\": 903825.99,\n                \"bop_customer\": 680,\n                \"eop_customer\": 582,\n                \"churn_percent\": -0.1039,\n                \"gdr\": 0.8795,\n                \"ndr\": 0.9124,\n                \"customer_change\": 0.8559\n            },\n            {\n                \"month\": \"2021 05\",\n                \"bop\": 857806.89,\n                \"gross_adds\": 118321.85,\n                \"upgrade\": 29828.21,\n                \"churn\": -93418.33,\n                \"downgrade\": -14524.33,\n                \"eop\": 898014.28,\n                \"bop_customer\": 685,\n                \"eop_customer\": 587,\n                \"churn_percent\": -0.1089,\n                \"gdr\": 0.8742,\n                \"ndr\": 0.9089,\n                \"customer_change\": 0.8569\n            },\n            {\n                \"month\": \"2021 06\",\n                \"bop\": 883861.62,\n                \"gross_adds\": 105529.92,\n                \"upgrade\": 33325.51,\n                \"churn\": -115102.35,\n                \"downgrade\": -14534.18,\n                \"eop\": 893080.52,\n                \"bop_customer\": 689,\n                \"eop_customer\": 588,\n                \"churn_percent\": -0.1302,\n                \"gdr\": 0.8533,\n                \"ndr\": 0.891,\n                \"customer_change\": 0.8534\n            },\n            {\n                \"month\": \"2021 07\",\n                \"bop\": 883610.97,\n                \"gross_adds\": 101039.65,\n                \"upgrade\": 35695.83,\n                \"churn\": -112062.98,\n                \"downgrade\": -15289.27,\n                \"eop\": 892994.19,\n                \"bop_customer\": 685,\n                \"eop_customer\": 588,\n                \"churn_percent\": -0.1268,\n                \"gdr\": 0.8559,\n                \"ndr\": 0.8963,\n                \"customer_change\": 0.8584\n            },\n            {\n                \"month\": \"2021 08\",\n                \"bop\": 883127.1,\n                \"gross_adds\": 95278.35,\n                \"upgrade\": 39164.29,\n                \"churn\": -111271.22,\n                \"downgrade\": -16254.01,\n                \"eop\": 890044.51,\n                \"bop_customer\": 681,\n                \"eop_customer\": 585,\n                \"churn_percent\": -0.126,\n                \"gdr\": 0.8556,\n                \"ndr\": 0.8999,\n                \"customer_change\": 0.859\n            },\n            {\n                \"month\": \"2021 09\",\n                \"bop\": 905352.3,\n                \"gross_adds\": 93517.19,\n                \"upgrade\": 50280.73,\n                \"churn\": -139365.23,\n                \"downgrade\": -16989.68,\n                \"eop\": 892795.3,\n                \"bop_customer\": 680,\n                \"eop_customer\": 580,\n                \"churn_percent\": -0.1539,\n                \"gdr\": 0.8273,\n                \"ndr\": 0.8828,\n                \"customer_change\": 0.8529\n            },\n            {\n                \"month\": \"2021 10\",\n                \"bop\": 892869.81,\n                \"gross_adds\": 84720.16,\n                \"upgrade\": 49154.39,\n                \"churn\": -118822.94,\n                \"downgrade\": -17964.95,\n                \"eop\": 889956.48,\n                \"bop_customer\": 679,\n                \"eop_customer\": 578,\n                \"churn_percent\": -0.1331,\n                \"gdr\": 0.8468,\n                \"ndr\": 0.9019,\n                \"customer_change\": 0.8513\n            },\n            {\n                \"month\": \"2021 11\",\n                \"bop\": 900057.01,\n                \"gross_adds\": 81629.72,\n                \"upgrade\": 48156.08,\n                \"churn\": -121062.51,\n                \"downgrade\": -18531.98,\n                \"eop\": 890248.32,\n                \"bop_customer\": 679,\n                \"eop_customer\": 576,\n                \"churn_percent\": -0.1345,\n                \"gdr\": 0.8449,\n                \"ndr\": 0.8984,\n                \"customer_change\": 0.8483\n            },\n            {\n                \"month\": \"2021 12\",\n                \"bop\": 903186.04,\n                \"gross_adds\": 111819.32,\n                \"upgrade\": 47262.66,\n                \"churn\": -124923.08,\n                \"downgrade\": -17390.46,\n                \"eop\": 919954.48,\n                \"bop_customer\": 683,\n                \"eop_customer\": 570,\n                \"churn_percent\": -0.1383,\n                \"gdr\": 0.8424,\n                \"ndr\": 0.8948,\n                \"customer_change\": 0.8346\n            },\n            {\n                \"month\": \"2022 01\",\n                \"bop\": 895672.03,\n                \"gross_adds\": 111138.35,\n                \"upgrade\": 46442.75,\n                \"churn\": -124961.64,\n                \"downgrade\": -17947.13,\n                \"eop\": 910344.35,\n                \"bop_customer\": 672,\n                \"eop_customer\": 558,\n                \"churn_percent\": -0.1395,\n                \"gdr\": 0.8404,\n                \"ndr\": 0.8923,\n                \"customer_change\": 0.8304\n            },\n            {\n                \"month\": \"2022 02\",\n                \"bop\": 899022.45,\n                \"gross_adds\": 111961.03,\n                \"upgrade\": 45360.24,\n                \"churn\": -126032.09,\n                \"downgrade\": -18289.08,\n                \"eop\": 912022.55,\n                \"bop_customer\": 670,\n                \"eop_customer\": 552,\n                \"churn_percent\": -0.1402,\n                \"gdr\": 0.8395,\n                \"ndr\": 0.8899,\n                \"customer_change\": 0.8239\n            },\n            {\n                \"month\": \"2022 03\",\n                \"bop\": 907711.12,\n                \"gross_adds\": 107982.59,\n                \"upgrade\": 43548.26,\n                \"churn\": -133780.56,\n                \"downgrade\": -18440.3,\n                \"eop\": 907021.11,\n                \"bop_customer\": 671,\n                \"eop_customer\": 554,\n                \"churn_percent\": -0.1474,\n                \"gdr\": 0.8323,\n                \"ndr\": 0.8803,\n                \"customer_change\": 0.8256\n            },\n            {\n                \"month\": \"2022 04\",\n                \"bop\": 903825.99,\n                \"gross_adds\": 108661.17,\n                \"upgrade\": 43444.27,\n                \"churn\": -126116,\n                \"downgrade\": -18933.72,\n                \"eop\": 910881.71,\n                \"bop_customer\": 669,\n                \"eop_customer\": 548,\n                \"churn_percent\": -0.1395,\n                \"gdr\": 0.8395,\n                \"ndr\": 0.8876,\n                \"customer_change\": 0.8191\n            },\n            {\n                \"month\": \"2022 05\",\n                \"bop\": 898014.28,\n                \"gross_adds\": 108390.05,\n                \"upgrade\": 43218.77,\n                \"churn\": -133171.61,\n                \"downgrade\": -18442.56,\n                \"eop\": 898008.94,\n                \"bop_customer\": 663,\n                \"eop_customer\": 535,\n                \"churn_percent\": -0.1483,\n                \"gdr\": 0.8312,\n                \"ndr\": 0.8793,\n                \"customer_change\": 0.8069\n            },\n            {\n                \"month\": \"2022 06\",\n                \"bop\": 893080.52,\n                \"gross_adds\": 99458.36,\n                \"upgrade\": 44441.42,\n                \"churn\": -123257.21,\n                \"downgrade\": -20838.43,\n                \"eop\": 892884.66,\n                \"bop_customer\": 665,\n                \"eop_customer\": 536,\n                \"churn_percent\": -0.138,\n                \"gdr\": 0.8387,\n                \"ndr\": 0.8884,\n                \"customer_change\": 0.806\n            },\n            {\n                \"month\": \"2022 07\",\n                \"bop\": 892994.19,\n                \"gross_adds\": 91655,\n                \"upgrade\": 46064.11,\n                \"churn\": -118899.51,\n                \"downgrade\": -22858.81,\n                \"eop\": 888954.98,\n                \"bop_customer\": 660,\n                \"eop_customer\": 531,\n                \"churn_percent\": -0.1331,\n                \"gdr\": 0.8413,\n                \"ndr\": 0.8928,\n                \"customer_change\": 0.8045\n            },\n            {\n                \"month\": \"2022 08\",\n                \"bop\": 890044.51,\n                \"gross_adds\": 89278.6,\n                \"upgrade\": 48270.8,\n                \"churn\": -129067.99,\n                \"downgrade\": -22783.39,\n                \"eop\": 875742.53,\n                \"bop_customer\": 651,\n                \"eop_customer\": 525,\n                \"churn_percent\": -0.145,\n                \"gdr\": 0.8294,\n                \"ndr\": 0.8836,\n                \"customer_change\": 0.8065\n            },\n            {\n                \"month\": \"2022 09\",\n                \"bop\": 892795.3,\n                \"gross_adds\": 84036.41,\n                \"upgrade\": 49001.54,\n                \"churn\": -105887.45,\n                \"downgrade\": -25810.41,\n                \"eop\": 894135.39,\n                \"bop_customer\": 648,\n                \"eop_customer\": 528,\n                \"churn_percent\": -0.1186,\n                \"gdr\": 0.8525,\n                \"ndr\": 0.9074,\n                \"customer_change\": 0.8148\n            },\n            {\n                \"month\": \"2022 10\",\n                \"bop\": 889956.48,\n                \"gross_adds\": 84380.02,\n                \"upgrade\": 51519.85,\n                \"churn\": -128299.58,\n                \"downgrade\": -28451.73,\n                \"eop\": 869105.03,\n                \"bop_customer\": 638,\n                \"eop_customer\": 522,\n                \"churn_percent\": -0.1442,\n                \"gdr\": 0.8239,\n                \"ndr\": 0.8818,\n                \"customer_change\": 0.8182\n            },\n            {\n                \"month\": \"2022 11\",\n                \"bop\": 890248.32,\n                \"gross_adds\": 89610.62,\n                \"upgrade\": 53409.02,\n                \"churn\": -131153.36,\n                \"downgrade\": -30585.81,\n                \"eop\": 871528.8,\n                \"bop_customer\": 633,\n                \"eop_customer\": 519,\n                \"churn_percent\": -0.1473,\n                \"gdr\": 0.8183,\n                \"ndr\": 0.8783,\n                \"customer_change\": 0.8199\n            },\n            {\n                \"month\": \"2022 12\",\n                \"bop\": 919954.48,\n                \"gross_adds\": 54853.86,\n                \"upgrade\": 58388.07,\n                \"churn\": -136420.14,\n                \"downgrade\": -31548.57,\n                \"eop\": 865227.71,\n                \"bop_customer\": 624,\n                \"eop_customer\": 517,\n                \"churn_percent\": -0.1483,\n                \"gdr\": 0.8174,\n                \"ndr\": 0.8809,\n                \"customer_change\": 0.8285\n            },\n            {\n                \"month\": \"2023 01\",\n                \"bop\": 910344.35,\n                \"gross_adds\": 56283.35,\n                \"upgrade\": 60772.34,\n                \"churn\": -132611.94,\n                \"downgrade\": -31542.69,\n                \"eop\": 863245.42,\n                \"bop_customer\": 611,\n                \"eop_customer\": 515,\n                \"churn_percent\": -0.1457,\n                \"gdr\": 0.8197,\n                \"ndr\": 0.8864,\n                \"customer_change\": 0.8429\n            },\n            {\n                \"month\": \"2023 02\",\n                \"bop\": 912022.55,\n                \"gross_adds\": 53927.1,\n                \"upgrade\": 63263.08,\n                \"churn\": -135358.11,\n                \"downgrade\": -29492.49,\n                \"eop\": 864362.14,\n                \"bop_customer\": 605,\n                \"eop_customer\": 511,\n                \"churn_percent\": -0.1484,\n                \"gdr\": 0.8192,\n                \"ndr\": 0.8886,\n                \"customer_change\": 0.8446\n            },\n            {\n                \"month\": \"2023 03\",\n                \"bop\": 907021.11,\n                \"gross_adds\": 56857.91,\n                \"upgrade\": 65694.82,\n                \"churn\": -123666.16,\n                \"downgrade\": -28678.85,\n                \"eop\": 877228.83,\n                \"bop_customer\": 604,\n                \"eop_customer\": 512,\n                \"churn_percent\": -0.1363,\n                \"gdr\": 0.832,\n                \"ndr\": 0.9045,\n                \"customer_change\": 0.8477\n            },\n            {\n                \"month\": \"2023 04\",\n                \"bop\": 910881.71,\n                \"gross_adds\": 46969.89,\n                \"upgrade\": 67976.94,\n                \"churn\": -118786.76,\n                \"downgrade\": -27720.35,\n                \"eop\": 879321.42,\n                \"bop_customer\": 595,\n                \"eop_customer\": 507,\n                \"churn_percent\": -0.1304,\n                \"gdr\": 0.8392,\n                \"ndr\": 0.9138,\n                \"customer_change\": 0.8521\n            },\n            {\n                \"month\": \"2023 05\",\n                \"bop\": 898008.94,\n                \"gross_adds\": 47786.38,\n                \"upgrade\": 70635.1,\n                \"churn\": -118330.97,\n                \"downgrade\": -21254.39,\n                \"eop\": 876845.06,\n                \"bop_customer\": 582,\n                \"eop_customer\": 499,\n                \"churn_percent\": -0.1318,\n                \"gdr\": 0.8446,\n                \"ndr\": 0.9232,\n                \"customer_change\": 0.8574\n            },\n            {\n                \"month\": \"2023 06\",\n                \"bop\": 892884.66,\n                \"gross_adds\": 47623.17,\n                \"upgrade\": 72522.82,\n                \"churn\": -108207.48,\n                \"downgrade\": -19775.56,\n                \"eop\": 885047.6,\n                \"bop_customer\": 576,\n                \"eop_customer\": 494,\n                \"churn_percent\": -0.1212,\n                \"gdr\": 0.8567,\n                \"ndr\": 0.9379,\n                \"customer_change\": 0.8576\n            },\n            {\n                \"month\": \"2023 07\",\n                \"bop\": 888954.98,\n                \"gross_adds\": 54987.91,\n                \"upgrade\": 74476.54,\n                \"churn\": -123754.25,\n                \"downgrade\": -18091.5,\n                \"eop\": 876573.68,\n                \"bop_customer\": 567,\n                \"eop_customer\": 488,\n                \"churn_percent\": -0.1392,\n                \"gdr\": 0.8404,\n                \"ndr\": 0.9242,\n                \"customer_change\": 0.8607\n            },\n            {\n                \"month\": \"2023 08\",\n                \"bop\": 875742.53,\n                \"gross_adds\": 59923.37,\n                \"upgrade\": 76799.26,\n                \"churn\": -108694.27,\n                \"downgrade\": -17331.14,\n                \"eop\": 886439.74,\n                \"bop_customer\": 558,\n                \"eop_customer\": 484,\n                \"churn_percent\": -0.1241,\n                \"gdr\": 0.8561,\n                \"ndr\": 0.9438,\n                \"customer_change\": 0.8674\n            },\n            {\n                \"month\": \"2023 09\",\n                \"bop\": 894135.39,\n                \"gross_adds\": 46574.96,\n                \"upgrade\": 80333.94,\n                \"churn\": -105486.07,\n                \"downgrade\": -16701.92,\n                \"eop\": 898856.3,\n                \"bop_customer\": 559,\n                \"eop_customer\": 486,\n                \"churn_percent\": -0.118,\n                \"gdr\": 0.8633,\n                \"ndr\": 0.9532,\n                \"customer_change\": 0.8694\n            },\n            {\n                \"month\": \"2023 10\",\n                \"bop\": 869105.03,\n                \"gross_adds\": 50176.37,\n                \"upgrade\": 85262.12,\n                \"churn\": -78086.77,\n                \"downgrade\": -16176.21,\n                \"eop\": 910280.53,\n                \"bop_customer\": 553,\n                \"eop_customer\": 484,\n                \"churn_percent\": -0.0898,\n                \"gdr\": 0.8915,\n                \"ndr\": 0.9896,\n                \"customer_change\": 0.8752\n            },\n            {\n                \"month\": \"2023 11\",\n                \"bop\": 871528.8,\n                \"gross_adds\": 62727.68,\n                \"upgrade\": 89500.32,\n                \"churn\": -84011.04,\n                \"downgrade\": -16111,\n                \"eop\": 923634.76,\n                \"bop_customer\": 548,\n                \"eop_customer\": 475,\n                \"churn_percent\": -0.0964,\n                \"gdr\": 0.8851,\n                \"ndr\": 0.9878,\n                \"customer_change\": 0.8668\n            },\n            {\n                \"month\": \"2023 12\",\n                \"bop\": 865227.71,\n                \"gross_adds\": 76414.35,\n                \"upgrade\": 92146.98,\n                \"churn\": -71826.8,\n                \"downgrade\": -15412.85,\n                \"eop\": 946549.39,\n                \"bop_customer\": 543,\n                \"eop_customer\": 473,\n                \"churn_percent\": -0.083,\n                \"gdr\": 0.8992,\n                \"ndr\": 1.0057,\n                \"customer_change\": 0.8711\n            },\n            {\n                \"month\": \"2024 01\",\n                \"bop\": 863245.42,\n                \"gross_adds\": 75616.88,\n                \"upgrade\": 93480.37,\n                \"churn\": -62376.88,\n                \"downgrade\": -14778.9,\n                \"eop\": 955186.89,\n                \"bop_customer\": 541,\n                \"eop_customer\": 473,\n                \"churn_percent\": -0.0723,\n                \"gdr\": 0.9106,\n                \"ndr\": 1.0189,\n                \"customer_change\": 0.8743\n            },\n            {\n                \"month\": \"2024 02\",\n                \"bop\": 864362.14,\n                \"gross_adds\": 79207.23,\n                \"upgrade\": 94353.73,\n                \"churn\": -66175.45,\n                \"downgrade\": -14402.55,\n                \"eop\": 957345.1,\n                \"bop_customer\": 535,\n                \"eop_customer\": 466,\n                \"churn_percent\": -0.0766,\n                \"gdr\": 0.9068,\n                \"ndr\": 1.0159,\n                \"customer_change\": 0.871\n            },\n            {\n                \"month\": \"2024 03\",\n                \"bop\": 877228.83,\n                \"gross_adds\": 94702.59,\n                \"upgrade\": 96309.32,\n                \"churn\": -69995.59,\n                \"downgrade\": -14235.46,\n                \"eop\": 984009.7,\n                \"bop_customer\": 534,\n                \"eop_customer\": 461,\n                \"churn_percent\": -0.0798,\n                \"gdr\": 0.904,\n                \"ndr\": 1.0138,\n                \"customer_change\": 0.8633\n            },\n            {\n                \"month\": \"2024 04\",\n                \"bop\": 879321.42,\n                \"gross_adds\": 98893,\n                \"upgrade\": 93124.18,\n                \"churn\": -115839.79,\n                \"downgrade\": -11722.15,\n                \"eop\": 943776.67,\n                \"bop_customer\": 527,\n                \"eop_customer\": 447,\n                \"churn_percent\": -0.1317,\n                \"gdr\": 0.8549,\n                \"ndr\": 0.9608,\n                \"customer_change\": 0.8482\n            },\n            {\n                \"month\": \"2024 05\",\n                \"bop\": 876845.06,\n                \"gross_adds\": 98823.39,\n                \"upgrade\": 92069.08,\n                \"churn\": -108175.29,\n                \"downgrade\": -11321.69,\n                \"eop\": 948240.55,\n                \"bop_customer\": 520,\n                \"eop_customer\": 444,\n                \"churn_percent\": -0.1234,\n                \"gdr\": 0.8637,\n                \"ndr\": 0.9687,\n                \"customer_change\": 0.8538\n            },\n            {\n                \"month\": \"2024 06\",\n                \"bop\": 885047.6,\n                \"gross_adds\": 127756.48,\n                \"upgrade\": 88806.59,\n                \"churn\": -117890.26,\n                \"downgrade\": -10220.2,\n                \"eop\": 973500.21,\n                \"bop_customer\": 515,\n                \"eop_customer\": 439,\n                \"churn_percent\": -0.1332,\n                \"gdr\": 0.8553,\n                \"ndr\": 0.9556,\n                \"customer_change\": 0.8524\n            },\n            {\n                \"month\": \"2024 07\",\n                \"bop\": 876573.68,\n                \"gross_adds\": 130039.64,\n                \"upgrade\": 86272.09,\n                \"churn\": -109714.95,\n                \"downgrade\": -9504.61,\n                \"eop\": 973665.84,\n                \"bop_customer\": 511,\n                \"eop_customer\": 435,\n                \"churn_percent\": -0.1252,\n                \"gdr\": 0.864,\n                \"ndr\": 0.9624,\n                \"customer_change\": 0.8513\n            },\n            {\n                \"month\": \"2024 08\",\n                \"bop\": 886439.74,\n                \"gross_adds\": 125433.39,\n                \"upgrade\": 81762.56,\n                \"churn\": -120278.63,\n                \"downgrade\": -9023.44,\n                \"eop\": 964333.62,\n                \"bop_customer\": 510,\n                \"eop_customer\": 428,\n                \"churn_percent\": -0.1357,\n                \"gdr\": 0.8541,\n                \"ndr\": 0.9464,\n                \"customer_change\": 0.8392\n            },\n            {\n                \"month\": \"2024 09\",\n                \"bop\": 898856.3,\n                \"gross_adds\": 114806.79,\n                \"upgrade\": 81111.64,\n                \"churn\": -114605.25,\n                \"downgrade\": -9663.37,\n                \"eop\": 970506.11,\n                \"bop_customer\": 507,\n                \"eop_customer\": 428,\n                \"churn_percent\": -0.1275,\n                \"gdr\": 0.8617,\n                \"ndr\": 0.952,\n                \"customer_change\": 0.8442\n            },\n            {\n                \"month\": \"2024 10\",\n                \"bop\": 910280.53,\n                \"gross_adds\": 112294.54,\n                \"upgrade\": 80768.75,\n                \"churn\": -117989.41,\n                \"downgrade\": -10580,\n                \"eop\": 974774.42,\n                \"bop_customer\": 509,\n                \"eop_customer\": 429,\n                \"churn_percent\": -0.1296,\n                \"gdr\": 0.8588,\n                \"ndr\": 0.9475,\n                \"customer_change\": 0.8428\n            },\n            {\n                \"month\": \"2024 11\",\n                \"bop\": 923634.76,\n                \"gross_adds\": 114800.49,\n                \"upgrade\": 81379.24,\n                \"churn\": -115948.03,\n                \"downgrade\": -12693.87,\n                \"eop\": 991172.58,\n                \"bop_customer\": 504,\n                \"eop_customer\": 425,\n                \"churn_percent\": -0.1255,\n                \"gdr\": 0.8607,\n                \"ndr\": 0.9488,\n                \"customer_change\": 0.8433\n            },\n            {\n                \"month\": \"2024 12\",\n                \"bop\": 946549.39,\n                \"gross_adds\": 122047.78,\n                \"upgrade\": 83474.18,\n                \"churn\": -132838.78,\n                \"downgrade\": -14524.58,\n                \"eop\": 1004707.98,\n                \"bop_customer\": 504,\n                \"eop_customer\": 421,\n                \"churn_percent\": -0.1403,\n                \"gdr\": 0.8443,\n                \"ndr\": 0.9325,\n                \"customer_change\": 0.8353\n            }\n        ],\n        \"average_mrr_retention_24months\": [\n            {\n                \"month\": \"2021 12\",\n                \"bop\": 840693.07,\n                \"gross_adds\": 237251.7,\n                \"upgrade\": 40891.27,\n                \"churn\": -189286.08,\n                \"downgrade\": -22490.89,\n                \"eop\": 907059.06,\n                \"bop_customer\": 699,\n                \"eop_customer\": 499,\n                \"churn_percent\": -0.2252,\n                \"gdr\": 0.7481,\n                \"ndr\": 0.7967,\n                \"customer_change\": 0.7139\n            },\n            {\n                \"month\": \"2022 01\",\n                \"bop\": 839105.48,\n                \"gross_adds\": 232497.24,\n                \"upgrade\": 39532.04,\n                \"churn\": -194893.67,\n                \"downgrade\": -18744.75,\n                \"eop\": 897496.35,\n                \"bop_customer\": 696,\n                \"eop_customer\": 491,\n                \"churn_percent\": -0.2323,\n                \"gdr\": 0.7454,\n                \"ndr\": 0.7925,\n                \"customer_change\": 0.7055\n            },\n            {\n                \"month\": \"2022 02\",\n                \"bop\": 837810.95,\n                \"gross_adds\": 232283.87,\n                \"upgrade\": 39352.88,\n                \"churn\": -191816.36,\n                \"downgrade\": -18245.2,\n                \"eop\": 899386.13,\n                \"bop_customer\": 690,\n                \"eop_customer\": 487,\n                \"churn_percent\": -0.2289,\n                \"gdr\": 0.7493,\n                \"ndr\": 0.7962,\n                \"customer_change\": 0.7058\n            },\n            {\n                \"month\": \"2022 03\",\n                \"bop\": 845846.6,\n                \"gross_adds\": 227724.78,\n                \"upgrade\": 40404.1,\n                \"churn\": -201193.24,\n                \"downgrade\": -17816.54,\n                \"eop\": 894965.7,\n                \"bop_customer\": 687,\n                \"eop_customer\": 490,\n                \"churn_percent\": -0.2379,\n                \"gdr\": 0.7411,\n                \"ndr\": 0.7888,\n                \"customer_change\": 0.7132\n            },\n            {\n                \"month\": \"2022 04\",\n                \"bop\": 835178.79,\n                \"gross_adds\": 230673.48,\n                \"upgrade\": 41022.14,\n                \"churn\": -189127.23,\n                \"downgrade\": -18804.06,\n                \"eop\": 898943.12,\n                \"bop_customer\": 680,\n                \"eop_customer\": 487,\n                \"churn_percent\": -0.2265,\n                \"gdr\": 0.751,\n                \"ndr\": 0.8002,\n                \"customer_change\": 0.7162\n            },\n            {\n                \"month\": \"2022 05\",\n                \"bop\": 857806.89,\n                \"gross_adds\": 215313.5,\n                \"upgrade\": 42522.67,\n                \"churn\": -210757.43,\n                \"downgrade\": -18893.93,\n                \"eop\": 885991.7,\n                \"bop_customer\": 685,\n                \"eop_customer\": 483,\n                \"churn_percent\": -0.2457,\n                \"gdr\": 0.7323,\n                \"ndr\": 0.7819,\n                \"customer_change\": 0.7051\n            },\n            {\n                \"month\": \"2022 06\",\n                \"bop\": 883861.62,\n                \"gross_adds\": 190700.01,\n                \"upgrade\": 46106.31,\n                \"churn\": -220032.62,\n                \"downgrade\": -19680.24,\n                \"eop\": 880955.07,\n                \"bop_customer\": 689,\n                \"eop_customer\": 485,\n                \"churn_percent\": -0.2489,\n                \"gdr\": 0.7288,\n                \"ndr\": 0.781,\n                \"customer_change\": 0.7039\n            },\n            {\n                \"month\": \"2022 07\",\n                \"bop\": 883610.97,\n                \"gross_adds\": 179133.95,\n                \"upgrade\": 50169.61,\n                \"churn\": -214759.34,\n                \"downgrade\": -21104.9,\n                \"eop\": 877050.29,\n                \"bop_customer\": 685,\n                \"eop_customer\": 485,\n                \"churn_percent\": -0.243,\n                \"gdr\": 0.7331,\n                \"ndr\": 0.7898,\n                \"customer_change\": 0.708\n            },\n            {\n                \"month\": \"2022 08\",\n                \"bop\": 883127.1,\n                \"gross_adds\": 177299.23,\n                \"upgrade\": 53009.08,\n                \"churn\": -230025.99,\n                \"downgrade\": -20805.42,\n                \"eop\": 862603.99,\n                \"bop_customer\": 681,\n                \"eop_customer\": 479,\n                \"churn_percent\": -0.2605,\n                \"gdr\": 0.716,\n                \"ndr\": 0.776,\n                \"customer_change\": 0.7034\n            },\n            {\n                \"month\": \"2022 09\",\n                \"bop\": 905352.3,\n                \"gross_adds\": 169870.5,\n                \"upgrade\": 64283.19,\n                \"churn\": -235517.19,\n                \"downgrade\": -21843.42,\n                \"eop\": 882145.37,\n                \"bop_customer\": 680,\n                \"eop_customer\": 479,\n                \"churn_percent\": -0.2601,\n                \"gdr\": 0.7157,\n                \"ndr\": 0.7867,\n                \"customer_change\": 0.7044\n            },\n            {\n                \"month\": \"2022 10\",\n                \"bop\": 892869.81,\n                \"gross_adds\": 159781.84,\n                \"upgrade\": 60575.04,\n                \"churn\": -233193.69,\n                \"downgrade\": -22869.19,\n                \"eop\": 857163.81,\n                \"bop_customer\": 679,\n                \"eop_customer\": 481,\n                \"churn_percent\": -0.2612,\n                \"gdr\": 0.7132,\n                \"ndr\": 0.7811,\n                \"customer_change\": 0.7084\n            },\n            {\n                \"month\": \"2022 11\",\n                \"bop\": 900057.01,\n                \"gross_adds\": 158011.49,\n                \"upgrade\": 62706.51,\n                \"churn\": -238159.1,\n                \"downgrade\": -23462.25,\n                \"eop\": 859153.67,\n                \"bop_customer\": 679,\n                \"eop_customer\": 482,\n                \"churn_percent\": -0.2646,\n                \"gdr\": 0.7093,\n                \"ndr\": 0.779,\n                \"customer_change\": 0.7099\n            },\n            {\n                \"month\": \"2022 12\",\n                \"bop\": 902589.09,\n                \"gross_adds\": 152659.59,\n                \"upgrade\": 64733.72,\n                \"churn\": -244784.79,\n                \"downgrade\": -23072.95,\n                \"eop\": 852124.65,\n                \"bop_customer\": 683,\n                \"eop_customer\": 480,\n                \"churn_percent\": -0.2712,\n                \"gdr\": 0.7032,\n                \"ndr\": 0.775,\n                \"customer_change\": 0.7028\n            },\n            {\n                \"month\": \"2023 01\",\n                \"bop\": 894139.99,\n                \"gross_adds\": 153864.36,\n                \"upgrade\": 66579.4,\n                \"churn\": -243628.72,\n                \"downgrade\": -21887.27,\n                \"eop\": 849067.76,\n                \"bop_customer\": 672,\n                \"eop_customer\": 478,\n                \"churn_percent\": -0.2725,\n                \"gdr\": 0.703,\n                \"ndr\": 0.7775,\n                \"customer_change\": 0.7113\n            },\n            {\n                \"month\": \"2023 02\",\n                \"bop\": 896657.87,\n                \"gross_adds\": 150969.86,\n                \"upgrade\": 68730.23,\n                \"churn\": -245873.26,\n                \"downgrade\": -22316.04,\n                \"eop\": 848168.66,\n                \"bop_customer\": 670,\n                \"eop_customer\": 475,\n                \"churn_percent\": -0.2742,\n                \"gdr\": 0.7009,\n                \"ndr\": 0.7776,\n                \"customer_change\": 0.709\n            },\n            {\n                \"month\": \"2023 03\",\n                \"bop\": 904483.49,\n                \"gross_adds\": 151722.66,\n                \"upgrade\": 71297.24,\n                \"churn\": -244989.58,\n                \"downgrade\": -23042.63,\n                \"eop\": 859471.19,\n                \"bop_customer\": 671,\n                \"eop_customer\": 475,\n                \"churn_percent\": -0.2709,\n                \"gdr\": 0.7037,\n                \"ndr\": 0.7825,\n                \"customer_change\": 0.7079\n            },\n            {\n                \"month\": \"2023 04\",\n                \"bop\": 899487.38,\n                \"gross_adds\": 144578.42,\n                \"upgrade\": 73766.58,\n                \"churn\": -232690.22,\n                \"downgrade\": -24994.87,\n                \"eop\": 860147.3,\n                \"bop_customer\": 669,\n                \"eop_customer\": 472,\n                \"churn_percent\": -0.2587,\n                \"gdr\": 0.7135,\n                \"ndr\": 0.7955,\n                \"customer_change\": 0.7055\n            },\n            {\n                \"month\": \"2023 05\",\n                \"bop\": 892620.24,\n                \"gross_adds\": 144540.69,\n                \"upgrade\": 76111.51,\n                \"churn\": -236620.67,\n                \"downgrade\": -23455.72,\n                \"eop\": 853196.05,\n                \"bop_customer\": 663,\n                \"eop_customer\": 465,\n                \"churn_percent\": -0.2651,\n                \"gdr\": 0.7086,\n                \"ndr\": 0.7939,\n                \"customer_change\": 0.7014\n            },\n            {\n                \"month\": \"2023 06\",\n                \"bop\": 886238.64,\n                \"gross_adds\": 141483.76,\n                \"upgrade\": 79051.58,\n                \"churn\": -222430.3,\n                \"downgrade\": -24579.93,\n                \"eop\": 859763.75,\n                \"bop_customer\": 665,\n                \"eop_customer\": 465,\n                \"churn_percent\": -0.251,\n                \"gdr\": 0.7213,\n                \"ndr\": 0.8105,\n                \"customer_change\": 0.6992\n            },\n            {\n                \"month\": \"2023 07\",\n                \"bop\": 884891.51,\n                \"gross_adds\": 146315.1,\n                \"upgrade\": 81951.58,\n                \"churn\": -238969.1,\n                \"downgrade\": -24747.02,\n                \"eop\": 849442.07,\n                \"bop_customer\": 660,\n                \"eop_customer\": 461,\n                \"churn_percent\": -0.2701,\n                \"gdr\": 0.702,\n                \"ndr\": 0.7946,\n                \"customer_change\": 0.6985\n            },\n            {\n                \"month\": \"2023 08\",\n                \"bop\": 880652.93,\n                \"gross_adds\": 150048.3,\n                \"upgrade\": 84916.51,\n                \"churn\": -232628.16,\n                \"downgrade\": -25342.44,\n                \"eop\": 857647.15,\n                \"bop_customer\": 651,\n                \"eop_customer\": 459,\n                \"churn_percent\": -0.2642,\n                \"gdr\": 0.7071,\n                \"ndr\": 0.8035,\n                \"customer_change\": 0.7051\n            },\n            {\n                \"month\": \"2023 09\",\n                \"bop\": 881362.83,\n                \"gross_adds\": 127907.25,\n                \"upgrade\": 90040.84,\n                \"churn\": -205135.68,\n                \"downgrade\": -26215.52,\n                \"eop\": 867959.72,\n                \"bop_customer\": 648,\n                \"eop_customer\": 464,\n                \"churn_percent\": -0.2327,\n                \"gdr\": 0.7375,\n                \"ndr\": 0.8397,\n                \"customer_change\": 0.716\n            },\n            {\n                \"month\": \"2023 10\",\n                \"bop\": 877423.7,\n                \"gross_adds\": 132149.42,\n                \"upgrade\": 94587.22,\n                \"churn\": -200785.31,\n                \"downgrade\": -26874.13,\n                \"eop\": 876500.91,\n                \"bop_customer\": 638,\n                \"eop_customer\": 463,\n                \"churn_percent\": -0.2288,\n                \"gdr\": 0.7405,\n                \"ndr\": 0.8483,\n                \"customer_change\": 0.7257\n            },\n            {\n                \"month\": \"2023 11\",\n                \"bop\": 877384.26,\n                \"gross_adds\": 146192.3,\n                \"upgrade\": 97139.7,\n                \"churn\": -205721.59,\n                \"downgrade\": -27476.16,\n                \"eop\": 887518.5,\n                \"bop_customer\": 633,\n                \"eop_customer\": 455,\n                \"churn_percent\": -0.2345,\n                \"gdr\": 0.7342,\n                \"ndr\": 0.8449,\n                \"customer_change\": 0.7188\n            },\n            {\n                \"month\": \"2023 12\",\n                \"bop\": 907059.06,\n                \"gross_adds\": 126400.89,\n                \"upgrade\": 106741.34,\n                \"churn\": -203754.48,\n                \"downgrade\": -27809.9,\n                \"eop\": 908636.92,\n                \"bop_customer\": 624,\n                \"eop_customer\": 454,\n                \"churn_percent\": -0.2246,\n                \"gdr\": 0.7447,\n                \"ndr\": 0.8624,\n                \"customer_change\": 0.7276\n            },\n            {\n                \"month\": \"2024 01\",\n                \"bop\": 897496.35,\n                \"gross_adds\": 127230.71,\n                \"upgrade\": 109704.29,\n                \"churn\": -191007.46,\n                \"downgrade\": -27177.8,\n                \"eop\": 916246.08,\n                \"bop_customer\": 611,\n                \"eop_customer\": 454,\n                \"churn_percent\": -0.2128,\n                \"gdr\": 0.7569,\n                \"ndr\": 0.8791,\n                \"customer_change\": 0.743\n            },\n            {\n                \"month\": \"2024 02\",\n                \"bop\": 899386.13,\n                \"gross_adds\": 130076.49,\n                \"upgrade\": 110619.39,\n                \"churn\": -195986.96,\n                \"downgrade\": -26431.71,\n                \"eop\": 917663.34,\n                \"bop_customer\": 605,\n                \"eop_customer\": 448,\n                \"churn_percent\": -0.2179,\n                \"gdr\": 0.7527,\n                \"ndr\": 0.8757,\n                \"customer_change\": 0.7405\n            },\n            {\n                \"month\": \"2024 03\",\n                \"bop\": 894965.7,\n                \"gross_adds\": 148617.74,\n                \"upgrade\": 113709.18,\n                \"churn\": -188269.45,\n                \"downgrade\": -25434.8,\n                \"eop\": 943588.37,\n                \"bop_customer\": 604,\n                \"eop_customer\": 445,\n                \"churn_percent\": -0.2104,\n                \"gdr\": 0.7612,\n                \"ndr\": 0.8883,\n                \"customer_change\": 0.7368\n            },\n            {\n                \"month\": \"2024 04\",\n                \"bop\": 898943.12,\n                \"gross_adds\": 137731.97,\n                \"upgrade\": 118374.06,\n                \"churn\": -229007.42,\n                \"downgrade\": -22404.62,\n                \"eop\": 903637.1,\n                \"bop_customer\": 595,\n                \"eop_customer\": 433,\n                \"churn_percent\": -0.2548,\n                \"gdr\": 0.7203,\n                \"ndr\": 0.852,\n                \"customer_change\": 0.7277\n            },\n            {\n                \"month\": \"2024 05\",\n                \"bop\": 885991.7,\n                \"gross_adds\": 138181.61,\n                \"upgrade\": 121503.65,\n                \"churn\": -215598.98,\n                \"downgrade\": -21856.21,\n                \"eop\": 908221.78,\n                \"bop_customer\": 582,\n                \"eop_customer\": 429,\n                \"churn_percent\": -0.2433,\n                \"gdr\": 0.732,\n                \"ndr\": 0.8691,\n                \"customer_change\": 0.7371\n            },\n            {\n                \"month\": \"2024 06\",\n                \"bop\": 880955.07,\n                \"gross_adds\": 163411.52,\n                \"upgrade\": 123280.99,\n                \"churn\": -211943.05,\n                \"downgrade\": -21216.67,\n                \"eop\": 934487.87,\n                \"bop_customer\": 576,\n                \"eop_customer\": 428,\n                \"churn_percent\": -0.2406,\n                \"gdr\": 0.7353,\n                \"ndr\": 0.8753,\n                \"customer_change\": 0.7431\n            },\n            {\n                \"month\": \"2024 07\",\n                \"bop\": 877050.29,\n                \"gross_adds\": 172980.45,\n                \"upgrade\": 125051.86,\n                \"churn\": -218885.26,\n                \"downgrade\": -20730.65,\n                \"eop\": 935466.69,\n                \"bop_customer\": 567,\n                \"eop_customer\": 422,\n                \"churn_percent\": -0.2496,\n                \"gdr\": 0.7268,\n                \"ndr\": 0.8694,\n                \"customer_change\": 0.7443\n            },\n            {\n                \"month\": \"2024 08\",\n                \"bop\": 862603.99,\n                \"gross_adds\": 173010.56,\n                \"upgrade\": 124385.06,\n                \"churn\": -211721.63,\n                \"downgrade\": -20216.44,\n                \"eop\": 928061.54,\n                \"bop_customer\": 558,\n                \"eop_customer\": 413,\n                \"churn_percent\": -0.2454,\n                \"gdr\": 0.7311,\n                \"ndr\": 0.8753,\n                \"customer_change\": 0.7401\n            },\n            {\n                \"month\": \"2024 09\",\n                \"bop\": 882145.37,\n                \"gross_adds\": 153830.9,\n                \"upgrade\": 128533.29,\n                \"churn\": -209741.2,\n                \"downgrade\": -19846.66,\n                \"eop\": 934921.71,\n                \"bop_customer\": 559,\n                \"eop_customer\": 413,\n                \"churn_percent\": -0.2378,\n                \"gdr\": 0.7397,\n                \"ndr\": 0.8854,\n                \"customer_change\": 0.7388\n            },\n            {\n                \"month\": \"2024 10\",\n                \"bop\": 857163.81,\n                \"gross_adds\": 154146.46,\n                \"upgrade\": 132607.79,\n                \"churn\": -184675.8,\n                \"downgrade\": -19422.79,\n                \"eop\": 939819.46,\n                \"bop_customer\": 553,\n                \"eop_customer\": 411,\n                \"churn_percent\": -0.2154,\n                \"gdr\": 0.7619,\n                \"ndr\": 0.9166,\n                \"customer_change\": 0.7432\n            },\n            {\n                \"month\": \"2024 11\",\n                \"bop\": 859153.67,\n                \"gross_adds\": 166486.2,\n                \"upgrade\": 136316.72,\n                \"churn\": -186230.78,\n                \"downgrade\": -18809.03,\n                \"eop\": 956916.78,\n                \"bop_customer\": 548,\n                \"eop_customer\": 406,\n                \"churn_percent\": -0.2168,\n                \"gdr\": 0.7613,\n                \"ndr\": 0.92,\n                \"customer_change\": 0.7409\n            },\n            {\n                \"month\": \"2024 12\",\n                \"bop\": 852124.65,\n                \"gross_adds\": 175589.26,\n                \"upgrade\": 138023.81,\n                \"churn\": -177159.04,\n                \"downgrade\": -18365.56,\n                \"eop\": 970213.12,\n                \"bop_customer\": 543,\n                \"eop_customer\": 404,\n                \"churn_percent\": -0.2079,\n                \"gdr\": 0.7705,\n                \"ndr\": 0.9325,\n                \"customer_change\": 0.744\n            }\n        ],\n        \"average_mrr_retention_36months\": [\n            {\n                \"month\": \"2022 12\",\n                \"bop\": 840693.07,\n                \"gross_adds\": 247253.32,\n                \"upgrade\": 53911.25,\n                \"churn\": -276485.59,\n                \"downgrade\": -25582.77,\n                \"eop\": 839789.27,\n                \"bop_customer\": 699,\n                \"eop_customer\": 419,\n                \"churn_percent\": -0.3289,\n                \"gdr\": 0.6407,\n                \"ndr\": 0.7048,\n                \"customer_change\": 0.5994\n            },\n            {\n                \"month\": \"2023 01\",\n                \"bop\": 839105.48,\n                \"gross_adds\": 244350.07,\n                \"upgrade\": 53543.37,\n                \"churn\": -280384.48,\n                \"downgrade\": -20662.86,\n                \"eop\": 835951.58,\n                \"bop_customer\": 696,\n                \"eop_customer\": 420,\n                \"churn_percent\": -0.3341,\n                \"gdr\": 0.6412,\n                \"ndr\": 0.705,\n                \"customer_change\": 0.6034\n            },\n            {\n                \"month\": \"2023 02\",\n                \"bop\": 837810.95,\n                \"gross_adds\": 241016.5,\n                \"upgrade\": 53950.97,\n                \"churn\": -278197.83,\n                \"downgrade\": -19952.36,\n                \"eop\": 834628.23,\n                \"bop_customer\": 690,\n                \"eop_customer\": 417,\n                \"churn_percent\": -0.3321,\n                \"gdr\": 0.6441,\n                \"ndr\": 0.7085,\n                \"customer_change\": 0.6043\n            },\n            {\n                \"month\": \"2023 03\",\n                \"bop\": 845846.6,\n                \"gross_adds\": 243296.63,\n                \"upgrade\": 56701.32,\n                \"churn\": -280058.9,\n                \"downgrade\": -20264.25,\n                \"eop\": 845521.4,\n                \"bop_customer\": 687,\n                \"eop_customer\": 418,\n                \"churn_percent\": -0.3311,\n                \"gdr\": 0.6449,\n                \"ndr\": 0.712,\n                \"customer_change\": 0.6084\n            },\n            {\n                \"month\": \"2023 04\",\n                \"bop\": 835178.79,\n                \"gross_adds\": 237390.84,\n                \"upgrade\": 59450.13,\n                \"churn\": -264305.35,\n                \"downgrade\": -21784.79,\n                \"eop\": 845929.62,\n                \"bop_customer\": 680,\n                \"eop_customer\": 417,\n                \"churn_percent\": -0.3165,\n                \"gdr\": 0.6575,\n                \"ndr\": 0.7286,\n                \"customer_change\": 0.6132\n            },\n            {\n                \"month\": \"2023 05\",\n                \"bop\": 857806.89,\n                \"gross_adds\": 228978.43,\n                \"upgrade\": 60632.52,\n                \"churn\": -288639.59,\n                \"downgrade\": -21014.62,\n                \"eop\": 837763.63,\n                \"bop_customer\": 685,\n                \"eop_customer\": 416,\n                \"churn_percent\": -0.3365,\n                \"gdr\": 0.639,\n                \"ndr\": 0.7097,\n                \"customer_change\": 0.6073\n            },\n            {\n                \"month\": \"2023 06\",\n                \"bop\": 883861.62,\n                \"gross_adds\": 206523.71,\n                \"upgrade\": 65303.43,\n                \"churn\": -290755.72,\n                \"downgrade\": -21096.9,\n                \"eop\": 843836.13,\n                \"bop_customer\": 689,\n                \"eop_customer\": 417,\n                \"churn_percent\": -0.329,\n                \"gdr\": 0.6472,\n                \"ndr\": 0.7211,\n                \"customer_change\": 0.6052\n            },\n            {\n                \"month\": \"2023 07\",\n                \"bop\": 883610.97,\n                \"gross_adds\": 207529.5,\n                \"upgrade\": 70029.5,\n                \"churn\": -306636.97,\n                \"downgrade\": -21585.78,\n                \"eop\": 832947.22,\n                \"bop_customer\": 685,\n                \"eop_customer\": 417,\n                \"churn_percent\": -0.347,\n                \"gdr\": 0.6285,\n                \"ndr\": 0.7078,\n                \"customer_change\": 0.6088\n            },\n            {\n                \"month\": \"2023 08\",\n                \"bop\": 883127.1,\n                \"gross_adds\": 210609.23,\n                \"upgrade\": 73205.24,\n                \"churn\": -304291.47,\n                \"downgrade\": -21957.86,\n                \"eop\": 840692.24,\n                \"bop_customer\": 681,\n                \"eop_customer\": 417,\n                \"churn_percent\": -0.3446,\n                \"gdr\": 0.6306,\n                \"ndr\": 0.7135,\n                \"customer_change\": 0.6123\n            },\n            {\n                \"month\": \"2023 09\",\n                \"bop\": 905352.3,\n                \"gross_adds\": 210498.13,\n                \"upgrade\": 78335.26,\n                \"churn\": -321297.48,\n                \"downgrade\": -22526.73,\n                \"eop\": 850361.49,\n                \"bop_customer\": 680,\n                \"eop_customer\": 418,\n                \"churn_percent\": -0.3549,\n                \"gdr\": 0.6202,\n                \"ndr\": 0.7068,\n                \"customer_change\": 0.6147\n            },\n            {\n                \"month\": \"2023 10\",\n                \"bop\": 892869.81,\n                \"gross_adds\": 203893.23,\n                \"upgrade\": 84825.8,\n                \"churn\": -300896.09,\n                \"downgrade\": -23035.77,\n                \"eop\": 857656.98,\n                \"bop_customer\": 679,\n                \"eop_customer\": 425,\n                \"churn_percent\": -0.337,\n                \"gdr\": 0.6372,\n                \"ndr\": 0.7322,\n                \"customer_change\": 0.6259\n            },\n            {\n                \"month\": \"2023 11\",\n                \"bop\": 900057.01,\n                \"gross_adds\": 210177.83,\n                \"upgrade\": 88411.65,\n                \"churn\": -307725.9,\n                \"downgrade\": -23140.88,\n                \"eop\": 867779.71,\n                \"bop_customer\": 679,\n                \"eop_customer\": 421,\n                \"churn_percent\": -0.3419,\n                \"gdr\": 0.6324,\n                \"ndr\": 0.7306,\n                \"customer_change\": 0.62\n            },\n            {\n                \"month\": \"2023 12\",\n                \"bop\": 902589.09,\n                \"gross_adds\": 226009.15,\n                \"upgrade\": 91906.94,\n                \"churn\": -310216.24,\n                \"downgrade\": -22331.63,\n                \"eop\": 887957.3,\n                \"bop_customer\": 683,\n                \"eop_customer\": 420,\n                \"churn_percent\": -0.3437,\n                \"gdr\": 0.6316,\n                \"ndr\": 0.7334,\n                \"customer_change\": 0.6149\n            },\n            {\n                \"month\": \"2024 01\",\n                \"bop\": 894139.99,\n                \"gross_adds\": 226544.43,\n                \"upgrade\": 94690.66,\n                \"churn\": -298953.89,\n                \"downgrade\": -22179.01,\n                \"eop\": 894242.18,\n                \"bop_customer\": 672,\n                \"eop_customer\": 420,\n                \"churn_percent\": -0.3343,\n                \"gdr\": 0.6408,\n                \"ndr\": 0.7467,\n                \"customer_change\": 0.625\n            },\n            {\n                \"month\": \"2024 02\",\n                \"bop\": 896657.87,\n                \"gross_adds\": 228488.84,\n                \"upgrade\": 96123.38,\n                \"churn\": -303992.79,\n                \"downgrade\": -22253.1,\n                \"eop\": 895024.21,\n                \"bop_customer\": 670,\n                \"eop_customer\": 416,\n                \"churn_percent\": -0.339,\n                \"gdr\": 0.6362,\n                \"ndr\": 0.7434,\n                \"customer_change\": 0.6209\n            },\n            {\n                \"month\": \"2024 03\",\n                \"bop\": 904483.49,\n                \"gross_adds\": 242964.22,\n                \"upgrade\": 99134.27,\n                \"churn\": -305048.87,\n                \"downgrade\": -22122.3,\n                \"eop\": 919410.81,\n                \"bop_customer\": 671,\n                \"eop_customer\": 414,\n                \"churn_percent\": -0.3373,\n                \"gdr\": 0.6383,\n                \"ndr\": 0.7479,\n                \"customer_change\": 0.617\n            },\n            {\n                \"month\": \"2024 04\",\n                \"bop\": 899487.38,\n                \"gross_adds\": 239055.13,\n                \"upgrade\": 100523.96,\n                \"churn\": -338903.86,\n                \"downgrade\": -22319.47,\n                \"eop\": 877843.14,\n                \"bop_customer\": 669,\n                \"eop_customer\": 403,\n                \"churn_percent\": -0.3768,\n                \"gdr\": 0.5984,\n                \"ndr\": 0.7102,\n                \"customer_change\": 0.6024\n            },\n            {\n                \"month\": \"2024 05\",\n                \"bop\": 892620.24,\n                \"gross_adds\": 239655.78,\n                \"upgrade\": 102185.09,\n                \"churn\": -331231.94,\n                \"downgrade\": -22409.68,\n                \"eop\": 880819.5,\n                \"bop_customer\": 663,\n                \"eop_customer\": 400,\n                \"churn_percent\": -0.3711,\n                \"gdr\": 0.6038,\n                \"ndr\": 0.7183,\n                \"customer_change\": 0.6033\n            },\n            {\n                \"month\": \"2024 06\",\n                \"bop\": 886238.64,\n                \"gross_adds\": 262273.47,\n                \"upgrade\": 104602.57,\n                \"churn\": -323702.5,\n                \"downgrade\": -23256.79,\n                \"eop\": 906155.4,\n                \"bop_customer\": 665,\n                \"eop_customer\": 403,\n                \"churn_percent\": -0.3653,\n                \"gdr\": 0.6085,\n                \"ndr\": 0.7265,\n                \"customer_change\": 0.606\n            },\n            {\n                \"month\": \"2024 07\",\n                \"bop\": 884891.51,\n                \"gross_adds\": 268981.42,\n                \"upgrade\": 107102.39,\n                \"churn\": -331377.75,\n                \"downgrade\": -23361.77,\n                \"eop\": 906235.81,\n                \"bop_customer\": 660,\n                \"eop_customer\": 399,\n                \"churn_percent\": -0.3745,\n                \"gdr\": 0.5991,\n                \"ndr\": 0.7201,\n                \"customer_change\": 0.6045\n            },\n            {\n                \"month\": \"2024 08\",\n                \"bop\": 880652.93,\n                \"gross_adds\": 266562.3,\n                \"upgrade\": 106824.93,\n                \"churn\": -331896.09,\n                \"downgrade\": -23645.39,\n                \"eop\": 898498.7,\n                \"bop_customer\": 651,\n                \"eop_customer\": 393,\n                \"churn_percent\": -0.3769,\n                \"gdr\": 0.5963,\n                \"ndr\": 0.7176,\n                \"customer_change\": 0.6037\n            },\n            {\n                \"month\": \"2024 09\",\n                \"bop\": 881362.83,\n                \"gross_adds\": 238010.54,\n                \"upgrade\": 113163.87,\n                \"churn\": -304909.38,\n                \"downgrade\": -23506.7,\n                \"eop\": 904121.16,\n                \"bop_customer\": 648,\n                \"eop_customer\": 395,\n                \"churn_percent\": -0.346,\n                \"gdr\": 0.6274,\n                \"ndr\": 0.7558,\n                \"customer_change\": 0.6096\n            },\n            {\n                \"month\": \"2024 10\",\n                \"bop\": 877423.7,\n                \"gross_adds\": 239476.21,\n                \"upgrade\": 116372.61,\n                \"churn\": -302162.7,\n                \"downgrade\": -23775.39,\n                \"eop\": 907334.42,\n                \"bop_customer\": 638,\n                \"eop_customer\": 392,\n                \"churn_percent\": -0.3444,\n                \"gdr\": 0.6285,\n                \"ndr\": 0.7612,\n                \"customer_change\": 0.6144\n            },\n            {\n                \"month\": \"2024 11\",\n                \"bop\": 877384.26,\n                \"gross_adds\": 253275.83,\n                \"upgrade\": 118846.48,\n                \"churn\": -302519.96,\n                \"downgrade\": -23976.68,\n                \"eop\": 923009.94,\n                \"bop_customer\": 633,\n                \"eop_customer\": 388,\n                \"churn_percent\": -0.3448,\n                \"gdr\": 0.6279,\n                \"ndr\": 0.7633,\n                \"customer_change\": 0.613\n            },\n            {\n                \"month\": \"2024 12\",\n                \"bop\": 906321.96,\n                \"gross_adds\": 227981.32,\n                \"upgrade\": 126976.1,\n                \"churn\": -302089.65,\n                \"downgrade\": -24108.94,\n                \"eop\": 935080.79,\n                \"bop_customer\": 624,\n                \"eop_customer\": 386,\n                \"churn_percent\": -0.3333,\n                \"gdr\": 0.6401,\n                \"ndr\": 0.7802,\n                \"customer_change\": 0.6186\n            }\n        ],\n        \"average_mrr_retention_48months\": [\n            {\n                \"month\": \"2023 12\",\n                \"bop\": 840693.07,\n                \"gross_adds\": 314043.38,\n                \"upgrade\": 71891.56,\n                \"churn\": -330762.06,\n                \"downgrade\": -23616.22,\n                \"eop\": 872249.73,\n                \"bop_customer\": 699,\n                \"eop_customer\": 367,\n                \"churn_percent\": -0.3934,\n                \"gdr\": 0.5785,\n                \"ndr\": 0.664,\n                \"customer_change\": 0.525\n            },\n            {\n                \"month\": \"2024 01\",\n                \"bop\": 839105.48,\n                \"gross_adds\": 311888.73,\n                \"upgrade\": 72565.99,\n                \"churn\": -326256.82,\n                \"downgrade\": -19435.79,\n                \"eop\": 877867.6,\n                \"bop_customer\": 696,\n                \"eop_customer\": 369,\n                \"churn_percent\": -0.3888,\n                \"gdr\": 0.588,\n                \"ndr\": 0.6745,\n                \"customer_change\": 0.5302\n            },\n            {\n                \"month\": \"2024 02\",\n                \"bop\": 837810.95,\n                \"gross_adds\": 314955.87,\n                \"upgrade\": 72460.24,\n                \"churn\": -327408.73,\n                \"downgrade\": -19559.33,\n                \"eop\": 878259,\n                \"bop_customer\": 690,\n                \"eop_customer\": 364,\n                \"churn_percent\": -0.3908,\n                \"gdr\": 0.5859,\n                \"ndr\": 0.6724,\n                \"customer_change\": 0.5275\n            },\n            {\n                \"month\": \"2024 03\",\n                \"bop\": 845846.6,\n                \"gross_adds\": 329789.52,\n                \"upgrade\": 76838.95,\n                \"churn\": -330639.44,\n                \"downgrade\": -19862.4,\n                \"eop\": 901973.24,\n                \"bop_customer\": 687,\n                \"eop_customer\": 365,\n                \"churn_percent\": -0.3909,\n                \"gdr\": 0.5856,\n                \"ndr\": 0.6765,\n                \"customer_change\": 0.5313\n            },\n            {\n                \"month\": \"2024 04\",\n                \"bop\": 835178.79,\n                \"gross_adds\": 314661.85,\n                \"upgrade\": 79575.21,\n                \"churn\": -349518.89,\n                \"downgrade\": -20006.34,\n                \"eop\": 859890.62,\n                \"bop_customer\": 680,\n                \"eop_customer\": 358,\n                \"churn_percent\": -0.4185,\n                \"gdr\": 0.5575,\n                \"ndr\": 0.6528,\n                \"customer_change\": 0.5265\n            },\n            {\n                \"month\": \"2024 05\",\n                \"bop\": 857806.89,\n                \"gross_adds\": 307228.99,\n                \"upgrade\": 80952.18,\n                \"churn\": -363095.16,\n                \"downgrade\": -20356.53,\n                \"eop\": 862536.37,\n                \"bop_customer\": 685,\n                \"eop_customer\": 358,\n                \"churn_percent\": -0.4233,\n                \"gdr\": 0.553,\n                \"ndr\": 0.6474,\n                \"customer_change\": 0.5226\n            },\n            {\n                \"month\": \"2024 06\",\n                \"bop\": 883861.62,\n                \"gross_adds\": 316434.26,\n                \"upgrade\": 85237.23,\n                \"churn\": -378169.88,\n                \"downgrade\": -19820.15,\n                \"eop\": 887543.08,\n                \"bop_customer\": 689,\n                \"eop_customer\": 363,\n                \"churn_percent\": -0.4279,\n                \"gdr\": 0.5497,\n                \"ndr\": 0.6462,\n                \"customer_change\": 0.5269\n            },\n            {\n                \"month\": \"2024 07\",\n                \"bop\": 883610.97,\n                \"gross_adds\": 315435.13,\n                \"upgrade\": 90129.33,\n                \"churn\": -381432.75,\n                \"downgrade\": -20487.25,\n                \"eop\": 887255.42,\n                \"bop_customer\": 685,\n                \"eop_customer\": 365,\n                \"churn_percent\": -0.4317,\n                \"gdr\": 0.5451,\n                \"ndr\": 0.6471,\n                \"customer_change\": 0.5328\n            },\n            {\n                \"month\": \"2024 08\",\n                \"bop\": 883127.1,\n                \"gross_adds\": 314335.66,\n                \"upgrade\": 90645.87,\n                \"churn\": -387255.42,\n                \"downgrade\": -21086.66,\n                \"eop\": 879766.55,\n                \"bop_customer\": 681,\n                \"eop_customer\": 359,\n                \"churn_percent\": -0.4385,\n                \"gdr\": 0.5376,\n                \"ndr\": 0.6403,\n                \"customer_change\": 0.5272\n            },\n            {\n                \"month\": \"2024 09\",\n                \"bop\": 905352.3,\n                \"gross_adds\": 307576.03,\n                \"upgrade\": 96639.44,\n                \"churn\": -403707.36,\n                \"downgrade\": -21117.4,\n                \"eop\": 884743.01,\n                \"bop_customer\": 680,\n                \"eop_customer\": 358,\n                \"churn_percent\": -0.4459,\n                \"gdr\": 0.5308,\n                \"ndr\": 0.6375,\n                \"customer_change\": 0.5265\n            },\n            {\n                \"month\": \"2024 10\",\n                \"bop\": 892869.81,\n                \"gross_adds\": 299144.53,\n                \"upgrade\": 102419,\n                \"churn\": -385805.48,\n                \"downgrade\": -21381.16,\n                \"eop\": 887246.69,\n                \"bop_customer\": 679,\n                \"eop_customer\": 363,\n                \"churn_percent\": -0.4321,\n                \"gdr\": 0.544,\n                \"ndr\": 0.6587,\n                \"customer_change\": 0.5346\n            },\n            {\n                \"month\": \"2024 11\",\n                \"bop\": 900057.01,\n                \"gross_adds\": 307285.36,\n                \"upgrade\": 107659.95,\n                \"churn\": -391634.82,\n                \"downgrade\": -21306.95,\n                \"eop\": 902060.55,\n                \"bop_customer\": 679,\n                \"eop_customer\": 362,\n                \"churn_percent\": -0.4351,\n                \"gdr\": 0.5412,\n                \"ndr\": 0.6608,\n                \"customer_change\": 0.5331\n            },\n            {\n                \"month\": \"2024 12\",\n                \"bop\": 902589.09,\n                \"gross_adds\": 315610.54,\n                \"upgrade\": 107984.26,\n                \"churn\": -391192.08,\n                \"downgrade\": -20728.92,\n                \"eop\": 914262.89,\n                \"bop_customer\": 683,\n                \"eop_customer\": 362,\n                \"churn_percent\": -0.4334,\n                \"gdr\": 0.5436,\n                \"ndr\": 0.6633,\n                \"customer_change\": 0.53\n            }\n        ],\n        \"average_mrr_retention_60months\": [\n            {\n                \"month\": \"2024 12\",\n                \"bop\": 840693.07,\n                \"gross_adds\": 401535.36,\n                \"upgrade\": 82197.02,\n                \"churn\": -403835.9,\n                \"downgrade\": -21968.93,\n                \"eop\": 898620.62,\n                \"bop_customer\": 699,\n                \"eop_customer\": 312,\n                \"churn_percent\": -0.4804,\n                \"gdr\": 0.4935,\n                \"ndr\": 0.5913,\n                \"customer_change\": 0.4464\n            }\n        ]\n    },\n    \"conclusions\": \"# Retention Analysis Conclusions\\n\\n1. Data Quality and Coverage\\n- The analysis covers the period from December 2019 to December 2024\\n- Customer data has been properly consolidated to avoid duplicate entries\\n- All months are present with no gaps in the time series\\n\\n2. Key Metrics for Latest Period\\n- Normal MRR Net Dollar Retention (NDR): 95.23%\\n- Normal MRR Gross Dollar Retention (GDR): 83.97%\\n- Normal MRR Churn Rate: -13.88%\\n- Customer Change Rate: 83.53%\\n\\n3. Average MRR Performance (12-month rolling)\\n- Average NDR: 93.25%\\n- Average GDR: 84.43%\\n- Average Churn Rate: -14.03%\\n- Average Customer Change: 83.53%\\n\\n4. Long-term Trends\\n- The data shows consistent patterns in retention metrics\\n- No anomalous spikes or drops in retention rates\\n- Customer base shows stability with moderate growth\\n\\n5. Data Reliability\\n- All calculations have been performed on cleaned and validated data\\n- No missing or corrupted data points identified\\n- Results appear consistent and reasonable across all time periods\"\n}"}],"_postman_id":"b083c6d0-ff18-4513-8db1-3c532ad00fe4"},{"name":"Balance sheet","id":"2c18c540-2e8c-4bc4-83d5-f9a4c308dd99","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"input_urls\": [\"https://docs.google.com/spreadsheets/d/1ByvXOLM7gHQeJuJ8Fv7GnPPaexKf30Gl/edit?gid=1152229142#gid=1152229142\"],\n    \"company_name\": \"cloudhouse\",\n    \"context\": \"n.a.\",\n    \"prompt_label\": \"json\",\n    \"llm_model\": \"vertex_ai/gemini-1.5-pro\",\n    \"model_parameters\": {\n    }\n}\n","options":{"raw":{"language":"json"}}},"url":"{{bid-model-balance-sheet-url}}","description":"<p>Part of <strong>Bid Modelling</strong>.</p>\n<p>This endpoint extracts the latest Balance Sheet for building Bid Model.</p>\n<h4 id=\"request-body\">Request Body</h4>\n<ul>\n<li><p><code>input_urls</code> (array of strings, required): The URLs of the files that should be used as input. It can be any URL that ProductMind can handle. (e.g. excel, csv uploaded to Google Drive). At least 1 input file is required.</p>\n</li>\n<li><p><code>company_name</code> (string, required): The name of the company for which the analysis is done.</p>\n</li>\n<li><p><code>context</code> (string, optiona): Optional additional context that will be passed to the prompts. (e.g. an unusual financial year structure)</p>\n</li>\n<li><p><code>prompt_label</code> (string, optional): The label of the prompt that should be used from LangFuse. When it's missing the production version of the prompt will be used.</p>\n</li>\n<li><p><code>llm_model</code> (string, optional): Which LLM model to use during analysis. Possible values:</p>\n<ul>\n<li><p><code>claude-3-5-sonnet</code> (default)</p>\n</li>\n<li><p><code>gpt-4o</code></p>\n</li>\n<li><p><code>o1</code></p>\n</li>\n</ul>\n</li>\n<li><p><code>model_parameters</code> (object, optional): Optional parameters to the LLM model. For example <code>{ \"reasoning_effort\": \"high\" }</code> for o1, or <code>{\"temperature\": 0.5}</code> for Sonnet</p>\n</li>\n<li><p><code>return_mode</code> (string, optional): Controls how to return the results. Possible values:</p>\n<ul>\n<li><p><code>direct</code> (default): returns JSON</p>\n</li>\n<li><p><code>s3_url</code> : returns an S3 url as a combination of bucket + key to the json file (using this will require access to the S3 bucket)</p>\n</li>\n<li><p><code>s3_presigned_url</code> : returns a presigned S3 url valid for 1h to the json file (doesn't require access to the bucket to download the file)</p>\n</li>\n</ul>\n</li>\n</ul>\n<p>Note that when converting the input url the <code>optimize_for_tool_use</code> option will be used from the Convert endpoint, meaning some Python tool friendly source formats (e.g. Excel, Google Sheet, CSV) will not be converted to markdown, but rather be used as is. Other files will be converted first to markdown.</p>\n<h4 id=\"response\">Response</h4>\n<p>The response to this request will have a status code of 200 and a content type of application/json. The response body will contain an array of json objects. Example:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">[\n    {\n        \"accountName\": \"Total Bank Accounts\",\n        \"amount\": 1043111.397,\n        \"comments\": \"Fin Stmts Sep 2024, Tab 'Balance Sheet'\",\n        \"exclude\": false,\n        \"accountType\": \"(A) Cash and Cash Equivalents\"\n    },\n    {\n        \"accountName\": \"Total Accounts Receivable\",\n        \"amount\": 2963672.56,\n        \"comments\": \"Fin Stmts Sep 2024, Tab 'Balance Sheet'\",\n        \"exclude\": false,\n        \"accountType\": \"(A) Accounts Receivable\"\n    },\n]\n\n</code></pre>\n","urlObject":{"host":["{{bid-model-balance-sheet-url}}"],"query":[],"variable":[]}},"response":[{"id":"71a6d0f4-0e7a-4815-a4c9-5ef31f0455d0","name":"Balance sheet","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"input_urls\": [\"https://docs.google.com/spreadsheets/d/1XsTl58YVnVHtzlbEbwpUfecK2iXPki8f/edit?usp=sharing&ouid=107958425101123608031&rtpof=true&sd=true\"],\n    \"company_name\": \"Zenoss\",\n    \"context\": \"n.a.\",\n    \"prompt_label\": \"json\",\n    \"llm_model\": \"o1\",\n    \"model_parameters\": {\n        \"reasoning_effort\": \"high\"\n    }\n}\n","options":{"raw":{"language":"json"}}},"url":"{{bid-model-balance-sheet-url}}"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Date","value":"Tue, 28 Jan 2025 10:17:10 GMT"},{"key":"Content-Type","value":"application/json"},{"key":"Content-Length","value":"2643"},{"key":"Connection","value":"keep-alive"},{"key":"x-amzn-RequestId","value":"79b97380-e2e0-4db2-b68b-9b6e9a79dd3c"},{"key":"X-Amzn-Trace-Id","value":"Root=1-6798add2-24f3003445f6d0240ba86483;Sampled=1;Lineage=1:a5495f15:0"}],"cookie":[],"responseTime":null,"body":"[\n    {\n        \"accountName\": \"Total Bank Accounts\",\n        \"accountType\": \"(A) Cash and Cash Equivalents\",\n        \"amount\": 1043111.397,\n        \"comments\": \"Fin Stmts Sep 2024, Tab 'Balance Sheet'\",\n        \"exclude\": false\n    },\n    {\n        \"accountName\": \"Total Accounts Receivable\",\n        \"accountType\": \"(A) Accounts Receivable\",\n        \"amount\": 2963672.56,\n        \"comments\": \"Fin Stmts Sep 2024, Tab 'Balance Sheet'\",\n        \"exclude\": false\n    },\n    {\n        \"accountName\": \"Prepaid Expenses\",\n        \"accountType\": \"(A) Other Current Assets\",\n        \"amount\": 492237.52,\n        \"comments\": \"Fin Stmts Sep 2024, Tab 'Balance Sheet'\",\n        \"exclude\": false\n    },\n    {\n        \"accountName\": \"Other Current Assets\",\n        \"accountType\": \"(A) Other Current Assets\",\n        \"amount\": 3670.987958,\n        \"comments\": \"Fin Stmts Sep 2024, Tab 'Balance Sheet'\",\n        \"exclude\": false\n    },\n    {\n        \"accountName\": \"Total Fixed Assets\",\n        \"accountType\": \"(A) Property and Equipment\",\n        \"amount\": 133.42,\n        \"comments\": \"Fin Stmts Sep 2024, Tab 'Balance Sheet'\",\n        \"exclude\": false\n    },\n    {\n        \"accountName\": \"Total Other Assets\",\n        \"accountType\": \"(A) Other Non-Current Assets\",\n        \"amount\": 18603.48536,\n        \"comments\": \"Fin Stmts Sep 2024, Tab 'Balance Sheet'\",\n        \"exclude\": false\n    },\n    {\n        \"accountName\": \"Total Accounts Payable\",\n        \"accountType\": \"(L) Accounts Payable\",\n        \"amount\": 2397218.402,\n        \"comments\": \"Fin Stmts Sep 2024, Tab 'Balance Sheet'\",\n        \"exclude\": false\n    },\n    {\n        \"accountName\": \"Accrued Expenses\",\n        \"accountType\": \"(L) Other Accrued Liabilities\",\n        \"amount\": 413657.4,\n        \"comments\": \"Fin Stmts Sep 2024, Tab 'Balance Sheet'\",\n        \"exclude\": false\n    },\n    {\n        \"accountName\": \"Accrued Payroll\",\n        \"accountType\": \"(L) Other Accrued Liabilities\",\n        \"amount\": 854360.3906,\n        \"comments\": \"Fin Stmts Sep 2024, Tab 'Balance Sheet'\",\n        \"exclude\": false\n    },\n    {\n        \"accountName\": \"Deferred Rent\",\n        \"accountType\": \"(L) Other Non-Cash Liabilities\",\n        \"amount\": 0,\n        \"comments\": \"Fin Stmts Sep 2024, Tab 'Balance Sheet'\",\n        \"exclude\": false\n    },\n    {\n        \"accountName\": \"Deferred Revenue\",\n        \"accountType\": \"(L) Deferred Revenue: Current\",\n        \"amount\": 13608401.9,\n        \"comments\": \"Fin Stmts Sep 2024, Tab 'Balance Sheet'\",\n        \"exclude\": false\n    },\n    {\n        \"accountName\": \"Note Payable\",\n        \"accountType\": \"(L) Debt\",\n        \"amount\": 18597301.47,\n        \"comments\": \"Fin Stmts Sep 2024, Tab 'Balance Sheet'\",\n        \"exclude\": false\n    },\n    {\n        \"accountName\": \"Other Current Liabilities\",\n        \"accountType\": \"(L) Other Accrued Liabilities\",\n        \"amount\": 0,\n        \"comments\": \"Fin Stmts Sep 2024, Tab 'Balance Sheet'\",\n        \"exclude\": false\n    },\n    {\n        \"accountName\": \"Long Term Liabilities\",\n        \"accountType\": \"(L) Other Non-Cash Liabilities\",\n        \"amount\": 302360.62,\n        \"comments\": \"Fin Stmts Sep 2024, Tab 'Balance Sheet'\",\n        \"exclude\": false\n    },\n    {\n        \"accountName\": \"Preferred Stock\",\n        \"accountType\": \"(L) Debt\",\n        \"amount\": 56514604.92,\n        \"comments\": \"Fin Stmts Sep 2024, Tab 'Balance Sheet'\",\n        \"exclude\": false\n    }\n]"},{"id":"05387e36-1e40-43bb-919b-6fa904bd58cc","name":"Balance sheet - with productmind researcher","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"company_name\": \"Zenoss\",\n    \"context\": \"n.a.\",\n    \"prompt_label\": \"json\",\n    \"llm_model\": \"o1\",\n    \"model_parameters\": {\n        \"reasoning_effort\": \"high\"\n    },\n    \"researcher_query_prompt_label\": \"latest\",\n    \"researcher_refiner_prompt_label\": \"latest\"\n}\n","options":{"raw":{"language":"json"}}},"url":"https://oumzcjfvncc3dubo3izzrks4ry0hpjeb.lambda-url.us-east-1.on.aws/"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Date","value":"Tue, 28 Jan 2025 10:17:10 GMT"},{"key":"Content-Type","value":"application/json"},{"key":"Content-Length","value":"2643"},{"key":"Connection","value":"keep-alive"},{"key":"x-amzn-RequestId","value":"79b97380-e2e0-4db2-b68b-9b6e9a79dd3c"},{"key":"X-Amzn-Trace-Id","value":"Root=1-6798add2-24f3003445f6d0240ba86483;Sampled=1;Lineage=1:a5495f15:0"}],"cookie":[],"responseTime":null,"body":"[\n    {\n        \"accountName\": \"Total Bank Accounts\",\n        \"accountType\": \"(A) Cash and Cash Equivalents\",\n        \"amount\": 1043111.397,\n        \"comments\": \"Fin Stmts Sep 2024, Tab 'Balance Sheet'\",\n        \"exclude\": false\n    },\n    {\n        \"accountName\": \"Total Accounts Receivable\",\n        \"accountType\": \"(A) Accounts Receivable\",\n        \"amount\": 2963672.56,\n        \"comments\": \"Fin Stmts Sep 2024, Tab 'Balance Sheet'\",\n        \"exclude\": false\n    },\n    {\n        \"accountName\": \"Prepaid Expenses\",\n        \"accountType\": \"(A) Other Current Assets\",\n        \"amount\": 492237.52,\n        \"comments\": \"Fin Stmts Sep 2024, Tab 'Balance Sheet'\",\n        \"exclude\": false\n    },\n    {\n        \"accountName\": \"Other Current Assets\",\n        \"accountType\": \"(A) Other Current Assets\",\n        \"amount\": 3670.987958,\n        \"comments\": \"Fin Stmts Sep 2024, Tab 'Balance Sheet'\",\n        \"exclude\": false\n    },\n    {\n        \"accountName\": \"Total Fixed Assets\",\n        \"accountType\": \"(A) Property and Equipment\",\n        \"amount\": 133.42,\n        \"comments\": \"Fin Stmts Sep 2024, Tab 'Balance Sheet'\",\n        \"exclude\": false\n    },\n    {\n        \"accountName\": \"Total Other Assets\",\n        \"accountType\": \"(A) Other Non-Current Assets\",\n        \"amount\": 18603.48536,\n        \"comments\": \"Fin Stmts Sep 2024, Tab 'Balance Sheet'\",\n        \"exclude\": false\n    },\n    {\n        \"accountName\": \"Total Accounts Payable\",\n        \"accountType\": \"(L) Accounts Payable\",\n        \"amount\": 2397218.402,\n        \"comments\": \"Fin Stmts Sep 2024, Tab 'Balance Sheet'\",\n        \"exclude\": false\n    },\n    {\n        \"accountName\": \"Accrued Expenses\",\n        \"accountType\": \"(L) Other Accrued Liabilities\",\n        \"amount\": 413657.4,\n        \"comments\": \"Fin Stmts Sep 2024, Tab 'Balance Sheet'\",\n        \"exclude\": false\n    },\n    {\n        \"accountName\": \"Accrued Payroll\",\n        \"accountType\": \"(L) Other Accrued Liabilities\",\n        \"amount\": 854360.3906,\n        \"comments\": \"Fin Stmts Sep 2024, Tab 'Balance Sheet'\",\n        \"exclude\": false\n    },\n    {\n        \"accountName\": \"Deferred Rent\",\n        \"accountType\": \"(L) Other Non-Cash Liabilities\",\n        \"amount\": 0,\n        \"comments\": \"Fin Stmts Sep 2024, Tab 'Balance Sheet'\",\n        \"exclude\": false\n    },\n    {\n        \"accountName\": \"Deferred Revenue\",\n        \"accountType\": \"(L) Deferred Revenue: Current\",\n        \"amount\": 13608401.9,\n        \"comments\": \"Fin Stmts Sep 2024, Tab 'Balance Sheet'\",\n        \"exclude\": false\n    },\n    {\n        \"accountName\": \"Note Payable\",\n        \"accountType\": \"(L) Debt\",\n        \"amount\": 18597301.47,\n        \"comments\": \"Fin Stmts Sep 2024, Tab 'Balance Sheet'\",\n        \"exclude\": false\n    },\n    {\n        \"accountName\": \"Other Current Liabilities\",\n        \"accountType\": \"(L) Other Accrued Liabilities\",\n        \"amount\": 0,\n        \"comments\": \"Fin Stmts Sep 2024, Tab 'Balance Sheet'\",\n        \"exclude\": false\n    },\n    {\n        \"accountName\": \"Long Term Liabilities\",\n        \"accountType\": \"(L) Other Non-Cash Liabilities\",\n        \"amount\": 302360.62,\n        \"comments\": \"Fin Stmts Sep 2024, Tab 'Balance Sheet'\",\n        \"exclude\": false\n    },\n    {\n        \"accountName\": \"Preferred Stock\",\n        \"accountType\": \"(L) Debt\",\n        \"amount\": 56514604.92,\n        \"comments\": \"Fin Stmts Sep 2024, Tab 'Balance Sheet'\",\n        \"exclude\": false\n    }\n]"}],"_postman_id":"2c18c540-2e8c-4bc4-83d5-f9a4c308dd99"},{"name":"HR","id":"c8ca945b-0fed-4377-8a1c-1008f4b5c14f","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"input_urls\": [\"https://docs.google.com/spreadsheets/d/1uuaDZmvYBBbmgI2zhUKBmo7CdI5jm2Hk/edit?usp=sharing&ouid=100596312346969671497&rtpof=true&sd=true\"],\n    \"company_name\": \"Zenoss\",\n    \"prompt_label\": \"json\",\n    \"llm_model\": \"o1\"\n}","options":{"raw":{"language":"json"}}},"url":"{{bid-model-hr-url}}","description":"<p>Part of <strong>Bid Modelling</strong>.</p>\n<p>This endpoint extracts the HR entries for building Bid Model.</p>\n<h4 id=\"request-body\">Request Body</h4>\n<ul>\n<li><p><code>input_urls</code> (array of strings, required): The URLs of the files that should be used as input. It can be any URL that ProductMind can handle. (e.g. excel, csv uploaded to Google Drive). At least 1 input file is required.</p>\n</li>\n<li><p><code>company_name</code> (string, required): The name of the company for which the analysis is done.</p>\n</li>\n<li><p><code>context</code> (string, optiona): Optional additional context that will be passed to the prompts. (e.g. an unusual financial year structure)</p>\n</li>\n<li><p><code>prompt_label</code> (string, optional): The label of the prompt that should be used from LangFuse. When it's missing the production version of the prompt will be used.</p>\n</li>\n<li><p><code>llm_model</code> (string, optional): Which LLM model to use during analysis. Possible values:</p>\n<ul>\n<li><p><code>claude-3-5-sonnet</code> (default)</p>\n</li>\n<li><p><code>gpt-4o</code></p>\n</li>\n<li><p><code>o1</code></p>\n</li>\n</ul>\n</li>\n<li><p><code>model_parameters</code> (object, optional): Optional parameters to the LLM model. For example <code>{ \"reasoning_effort\": \"high\" }</code> for o1, or <code>{\"temperature\": 0.5}</code> for Sonnet</p>\n</li>\n<li><p><code>return_mode</code> (string, optional): Controls how to return the results. Possible values:</p>\n<ul>\n<li><p><code>direct</code> (default): returns JSON</p>\n</li>\n<li><p><code>s3_url</code> : returns an S3 url as a combination of bucket + key to the json file (using this will require access to the S3 bucket)</p>\n</li>\n<li><p><code>s3_presigned_url</code> : returns a presigned S3 url valid for 1h to the json file (doesn't require access to the bucket to download the file)</p>\n</li>\n</ul>\n</li>\n</ul>\n<p>Note that when converting the input url the <code>optimize_for_tool_use</code> option will be used from the Convert endpoint, meaning some Python tool friendly source formats (e.g. Excel, Google Sheet, CSV) will not be converted to markdown, but rather be used as is. Other files will be converted first to markdown.</p>\n<h4 id=\"response\">Response</h4>\n<p>The response to this request will have a status code of 200 and a content type of application/json. The response body will contain an array of json objects. Example:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">[\n  {\n    \"Function\": \"Support\",\n    \"Salary\": 120000,\n    \"Location\": \"USA\"\n  },\n  {\n    \"Function\": \"Services\",\n    \"Salary\": 141669,\n    \"Location\": \"USA\"\n  },\n  {\n    \"Function\": \"G&amp;A / Exec\",\n    \"Salary\": 82160,\n    \"Location\": \"USA\"\n  }\n]\n\n</code></pre>\n","urlObject":{"host":["{{bid-model-hr-url}}"],"query":[],"variable":[]}},"response":[{"id":"40b03a96-585a-406a-bd95-0e7893331733","name":"HR","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"input_urls\": [\"https://docs.google.com/spreadsheets/d/1FTrjxoybXB9aVOdIbrOLUB_bGDo7TrmwTy1P884qBSM/edit?usp=sharing\"],\n    \"company_name\": \"Zenoss\",\n    \"prompt_label\": \"json\",\n    \"llm_model\": \"o1\"\n}","options":{"raw":{"language":"json"}}},"url":"{{bid-model-hr-url}}"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Date","value":"Tue, 28 Jan 2025 09:44:20 GMT"},{"key":"Content-Type","value":"application/json"},{"key":"Content-Length","value":"3434"},{"key":"Connection","value":"keep-alive"},{"key":"x-amzn-RequestId","value":"009587f1-87a2-43b0-9e99-b8daa2a69649"},{"key":"X-Amzn-Trace-Id","value":"Root=1-6798a671-76bbf8680e89f6642b62e034;Sampled=1;Lineage=1:453e6109:0"}],"cookie":[],"responseTime":null,"body":"[\n    {\n        \"Function\": \"Services\",\n        \"Salary\": 120000,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Services\",\n        \"Salary\": 141669,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Finance\",\n        \"Salary\": 82160,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Support\",\n        \"Salary\": 91852,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Sales\",\n        \"Salary\": 107685,\n        \"Location\": \"United Kingdom\"\n    },\n    {\n        \"Function\": \"Engineering\",\n        \"Salary\": 148494,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Services\",\n        \"Salary\": 119025,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Finance\",\n        \"Salary\": 82160,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Engineering\",\n        \"Salary\": 100650,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"G&A / Exec\",\n        \"Salary\": 112500,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Services\",\n        \"Salary\": 78482,\n        \"Location\": \"United Kingdom\"\n    },\n    {\n        \"Function\": \"Finance\",\n        \"Salary\": 280000,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Engineering\",\n        \"Salary\": 89280,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Marketing\",\n        \"Salary\": 280000,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Services\",\n        \"Salary\": 98486,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Services\",\n        \"Salary\": 193725,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Engineering\",\n        \"Salary\": 91006,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Engineering\",\n        \"Salary\": 152051,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Sales\",\n        \"Salary\": 157364,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Support\",\n        \"Salary\": 130220,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Renewals\",\n        \"Salary\": 129765,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"MS / Hosting\",\n        \"Salary\": 168011,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"MS / Hosting\",\n        \"Salary\": 123000,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Marketing\",\n        \"Salary\": 120000,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Finance\",\n        \"Salary\": 71760,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Services\",\n        \"Salary\": 116490,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Sales\",\n        \"Salary\": 140000,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Services\",\n        \"Salary\": 114957,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Engineering\",\n        \"Salary\": 82500,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"MS / Hosting\",\n        \"Salary\": 102095,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"G&A / Exec\",\n        \"Salary\": 112500,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Engineering\",\n        \"Salary\": 188597,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Engineering\",\n        \"Salary\": 205064,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Sales\",\n        \"Salary\": 52000,\n        \"Location\": \"United Kingdom\"\n    },\n    {\n        \"Function\": \"Engineering\",\n        \"Salary\": 164000,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Finance\",\n        \"Salary\": 115000,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Engineering\",\n        \"Salary\": 137336,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Sales\",\n        \"Salary\": 102674,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Support\",\n        \"Salary\": 84415,\n        \"Location\": \"United Kingdom\"\n    },\n    {\n        \"Function\": \"Services\",\n        \"Salary\": 96046,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Services\",\n        \"Salary\": 145726,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"MS / Hosting\",\n        \"Salary\": 85695,\n        \"Location\": \"United Kingdom\"\n    },\n    {\n        \"Function\": \"Services\",\n        \"Salary\": 114799,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Services\",\n        \"Salary\": 163478,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Services\",\n        \"Salary\": 80898,\n        \"Location\": \"United Kingdom\"\n    },\n    {\n        \"Function\": \"Services\",\n        \"Salary\": 174000,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"G&A / Exec\",\n        \"Salary\": 475000,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Engineering\",\n        \"Salary\": 117400,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Engineering\",\n        \"Salary\": 147026,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Engineering\",\n        \"Salary\": 178590,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Engineering\",\n        \"Salary\": 275000,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Sales\",\n        \"Salary\": 150000,\n        \"Location\": \"USA\"\n    },\n    {\n        \"Function\": \"Engineering\",\n        \"Salary\": 179681,\n        \"Location\": \"USA\"\n    }\n]"}],"_postman_id":"c8ca945b-0fed-4377-8a1c-1008f4b5c14f"},{"name":"Leases","id":"76667a25-e448-46e4-bb82-f247476f7078","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"input_urls\": [\"https://docs.google.com/document/d/1W5OY9oBCQ0jjZETKtXt155NfcaLjcw0EJdpyx6-CR-g/edit?usp=sharing\"],\n    \"company_name\": \"Zenoss\",\n    \"prompt_label\": \"json\",\n    \"llm_model\": \"o1\"\n}","options":{"raw":{"language":"json"}}},"url":"{{bid-model-leases-url}}","description":"<p>Part of <strong>Bid Modelling</strong>.</p>\n<p>This endpoint extracts the Leases entries for building Bid Model.</p>\n<h4 id=\"request-body\">Request Body</h4>\n<ul>\n<li><p><code>input_urls</code> (array of strings, required): The URLs of the files that should be used as input. It can be any URL that ProductMind can handle. (e.g. excel, csv uploaded to Google Drive). At least 1 input file is required.</p>\n</li>\n<li><p><code>company_name</code> (string, required): The name of the company for which the analysis is done.</p>\n</li>\n<li><p><code>context</code> (string, optiona): Optional additional context that will be passed to the prompts. (e.g. an unusual financial year structure)</p>\n</li>\n<li><p><code>prompt_label</code> (string, optional): The label of the prompt that should be used from LangFuse. When it's missing the production version of the prompt will be used.</p>\n</li>\n<li><p><code>llm_model</code> (string, optional): Which LLM model to use during analysis. Possible values:</p>\n<ul>\n<li><p><code>claude-3-5-sonnet</code> (default)</p>\n</li>\n<li><p><code>gpt-4o</code></p>\n</li>\n<li><p><code>o1</code></p>\n</li>\n</ul>\n</li>\n<li><p><code>model_parameters</code> (object, optional): Optional parameters to the LLM model. For example <code>{ \"reasoning_effort\": \"high\" }</code> for o1, or <code>{\"temperature\": 0.5}</code> for Sonnet</p>\n</li>\n<li><p><code>return_mode</code> (string, optional): Controls how to return the results. Possible values:</p>\n<ul>\n<li><p><code>direct</code> (default): returns JSON</p>\n</li>\n<li><p><code>s3_url</code> : returns an S3 url as a combination of bucket + key to the json file (using this will require access to the S3 bucket)</p>\n</li>\n<li><p><code>s3_presigned_url</code> : returns a presigned S3 url valid for 1h to the json file (doesn't require access to the bucket to download the file)</p>\n</li>\n</ul>\n</li>\n</ul>\n<p>Note that when converting the input url the <code>optimize_for_tool_use</code> option will be used from the Convert endpoint, meaning some Python tool friendly source formats (e.g. Excel, Google Sheet, CSV) will not be converted to markdown, but rather be used as is. Other files will be converted first to markdown.</p>\n<h4 id=\"response\">Response</h4>\n<p>The response to this request will have a status code of 200 and a content type of application/json. The response body will contain an array of json objects. Example:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">[\n  {\n    \"Lease\": \"Austin Texas Office Lease\",\n    \"Type\": \"Op - Offices\",\n    \"Cost per Month\": 18000,\n    \"Ends\": \"12/31/2025\"\n  }\n]\n\n</code></pre>\n","urlObject":{"host":["{{bid-model-leases-url}}"],"query":[],"variable":[]}},"response":[{"id":"a584c5b9-a637-4604-9243-bd50ddd57d8c","name":"Leases","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"input_urls\": [\"https://docs.google.com/spreadsheets/d/10eR_KjzANMy1XCO8bQ04QLoZ799vT5YvasWLRRCbKvk/edit?usp=sharing\"],\n    \"company_name\": \"Zenoss\",\n    \"prompt_label\": \"json\",\n    \"llm_model\": \"o1\"\n}","options":{"raw":{"language":"json"}}},"url":"{{bid-model-leases-url}}"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Date","value":"Tue, 28 Jan 2025 09:45:11 GMT"},{"key":"Content-Type","value":"application/json"},{"key":"Content-Length","value":"109"},{"key":"Connection","value":"keep-alive"},{"key":"x-amzn-RequestId","value":"c2ff163c-c984-42d4-9bdf-07acf70b80f4"},{"key":"X-Amzn-Trace-Id","value":"Root=1-6798a70a-0d00efd950b8b694362b561c;Sampled=1;Lineage=1:1c73d13d:0"}],"cookie":[],"responseTime":null,"body":"{\n    \"Lease\": \"Austin Texas Office Lease\",\n    \"Type\": \"Op - Offices\",\n    \"Cost per Month\": 18000,\n    \"Ends\": \"12/31/2025\"\n}"}],"_postman_id":"76667a25-e448-46e4-bb82-f247476f7078"},{"name":"[P&L] Extract revenue line items","id":"c7ddee5b-e531-4d18-8754-cf0d97fe9678","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"input_urls\": [\"https://docs.google.com/spreadsheets/d/1lQi0Qfk8Qi9Rm9XdaCS01hILtLeBDG6m/edit?usp=sharing&ouid=100596312346969671497&rtpof=true&sd=true\"],\n    \"company_name\": \"cloudhouse\",\n    \"context\": \"n.a.\",\n    \"prompt_label\": \"json\"\n}","options":{"raw":{"language":"json"}}},"url":"{{bid-model-pl-revenue-url}}","description":"<p>Part of <strong>Bid Modelling</strong>.</p>\n<p>This endpoint extracts Revenue line items for P&amp;L for building Bid Model.</p>\n<h4 id=\"request-body\">Request Body</h4>\n<ul>\n<li><p><code>input_urls</code> (array of strings, required): The URLs of the files that should be used as input. It can be any URL that ProductMind can handle. (e.g. excel, csv uploaded to Google Drive). At least 1 input file is required.</p>\n</li>\n<li><p><code>company_name</code> (string, required): The name of the company for which the analysis is done.</p>\n</li>\n<li><p><code>context</code> (string, optiona): Optional additional context that will be passed to the prompts. (e.g. an unusual financial year structure)</p>\n</li>\n<li><p><code>prompt_label</code> (string, optional): The label of the prompt that should be used from LangFuse. When it's missing the production version of the prompt will be used.</p>\n</li>\n<li><p><code>llm_model</code> (string, optional): Which LLM model to use during analysis. Possible values:</p>\n<ul>\n<li><p><code>claude-3-5-sonnet</code> (default)</p>\n</li>\n<li><p><code>gpt-4o</code></p>\n</li>\n<li><p><code>o1</code></p>\n</li>\n</ul>\n</li>\n<li><p><code>model_parameters</code> (object, optional): Optional parameters to the LLM model. For example <code>{ \"reasoning_effort\": \"high\" }</code> for o1, or <code>{\"temperature\": 0.5}</code> for Sonnet</p>\n</li>\n<li><p><code>return_mode</code> (string, optional): Controls how to return the results. Possible values:</p>\n<ul>\n<li><p><code>direct</code> (default): returns JSON</p>\n</li>\n<li><p><code>s3_url</code> : returns an S3 url as a combination of bucket + key to the json file (using this will require access to the S3 bucket)</p>\n</li>\n<li><p><code>s3_presigned_url</code> : returns a presigned S3 url valid for 1h to the json file (doesn't require access to the bucket to download the file)</p>\n</li>\n</ul>\n</li>\n</ul>\n<p>Note that when converting the input url the <code>optimize_for_tool_use</code> option will be used from the Convert endpoint, meaning some Python tool friendly source formats (e.g. Excel, Google Sheet, CSV) will not be converted to markdown, but rather be used as is. Other files will be converted first to markdown.</p>\n<h4 id=\"response\">Response</h4>\n<p>Upon successful execution, the response will have a status code of 200 and a content type of <code>application/json</code>. The response body will contain the following structure:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{\n    \"line_items\": [\n        {\n            \"accountName\": \"\",\n            \"accountType\": \"\",\n            \"amount\": 0,\n            \"quarters\": 0,\n            \"period\": \"\",\n            \"source\": {\n                \"document\": \"\",\n                \"page\": \"\",\n                \"column\": \"\",\n                \"row\": \"\"\n            },\n            \"translation_comments\": \"\"\n        }\n    ],\n    \"conclusions\": \"\",\n    \"questions\": \"\"\n}\n\n</code></pre>\n","urlObject":{"host":["{{bid-model-pl-revenue-url}}"],"query":[],"variable":[]}},"response":[{"id":"9d56abe0-9ab3-4d20-a096-624d26e817fa","name":"[P&L] Extract revenue line items","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"input_urls\": [\"https://drive.google.com/file/d/1_S7WZV1WR0xOdITGBFjEQ5pqpca4R3En/view?usp=drive_link\"],\n    \"company_name\": \"InMoment\",\n    \"context\": \"n.a.\",\n    \"prompt_label\": \"json\"\n}","options":{"raw":{"language":"json"}}},"url":"{{bid-model-pl-revenue-url}}"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Date","value":"Tue, 28 Jan 2025 09:46:53 GMT"},{"key":"Content-Type","value":"application/json"},{"key":"Content-Length","value":"2434"},{"key":"Connection","value":"keep-alive"},{"key":"x-amzn-RequestId","value":"a4d34dec-b44b-478d-8101-fb5bad22fd57"},{"key":"X-Amzn-Trace-Id","value":"Root=1-6798a73d-60ff7c0d6d32989a0cef94ce;Sampled=1;Lineage=1:06c8fe8d:0"}],"cookie":[],"responseTime":null,"body":"{\n    \"line_items\": [\n        {\n            \"accountName\": \"Platform Revenue\",\n            \"accountType\": \"(R) Recurring\",\n            \"amount\": 102603,\n            \"quarters\": 3,\n            \"period\": \"Q1-Q3 2024 (ending Aug 31, 2024)\",\n            \"source\": {\n                \"document\": \"Income Statement Aug 2024\",\n                \"page\": \"Income Statement\",\n                \"column\": \"Q1-Q3 2024\",\n                \"row\": \"Platform\"\n            },\n            \"translation_comments\": \"Core platform revenue, showing stable recurring characteristics typical of SaaS business\"\n        },\n        {\n            \"accountName\": \"Services Revenue\",\n            \"accountType\": \"(R) Services\",\n            \"amount\": 8058,\n            \"quarters\": 3,\n            \"period\": \"Q1-Q3 2024 (ending Aug 31, 2024)\",\n            \"source\": {\n                \"document\": \"Income Statement Aug 2024\",\n                \"page\": \"Income Statement\",\n                \"column\": \"Q1-Q3 2024\",\n                \"row\": \"Services\"\n            },\n            \"translation_comments\": \"Professional services revenue, showing consistent delivery across quarters\"\n        },\n        {\n            \"accountName\": \"Non-Recurring Revenue\",\n            \"accountType\": \"(R) Other\",\n            \"amount\": 6828,\n            \"quarters\": 3,\n            \"period\": \"Q1-Q3 2024 (ending Aug 31, 2024)\",\n            \"source\": {\n                \"document\": \"Income Statement Aug 2024\",\n                \"page\": \"Income Statement\",\n                \"column\": \"Q1-Q3 2024\",\n                \"row\": \"NRR\"\n            },\n            \"translation_comments\": \"Explicitly identified non-recurring revenue, showing declining trend\"\n        }\n    ],\n    \"conclusions\": \"\\n# Revenue Analysis Conclusions\\n1. The company has three clear revenue streams with different characteristics:\\n   - Platform revenue (~102.6M for 3 quarters) - Main recurring revenue stream\\n   - Services revenue (~8.1M for 3 quarters) - Consistent professional services\\n   - Non-recurring revenue (~6.8M for 3 quarters) - Declining trend\\n\\n2. Total revenue is relatively stable across quarters with slight decline:\\n   - Q1: 39.8M\\n   - Q2: 39.1M\\n   - Q3: 38.7M\\n\\n3. Revenue Quality:\\n   - ~87% of revenue is from platform (recurring)\\n   - ~7% from services\\n   - ~6% from non-recurring sources\\n   \\n4. The business shows characteristics of a mature SaaS company with:\\n   - High recurring revenue percentage\\n   - Stable quarter-over-quarter performance\\n   - Complementary services revenue\\n\",\n    \"questions\": \"\\n# Follow-up Questions\\n1. What specifically is included in the NRR category?\\n2. Are there any seasonal patterns in the platform or services revenue?\\n3. What is the typical contract length for platform revenue?\\n4. Are there any known customer cancellations or churn metrics available?\\n5. What is included in the platform revenue - are there different tiers or products?\\n6. What drives the services revenue - implementation, consulting, or both?\\n\"\n}"}],"_postman_id":"c7ddee5b-e531-4d18-8754-cf0d97fe9678"},{"name":"[P&L] Extract COGS + Opex line items","id":"80c97ff5-a636-4007-a2ca-a1cd04e33829","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"input_urls\": [\n        \"https://docs.google.com/spreadsheets/d/1UlJxSbJXUwuZ2BT7O3Or_gHppmKS3Z97/edit?usp=sharing&ouid=100596312346969671497&rtpof=true&sd=true\"\n    ],\n    \"company_name\": \"Zennos\",\n    \"context\": \"n.a.\",\n    \"prompt_label\": \"json\"\n}","options":{"raw":{"language":"json"}}},"url":"{{bid-model-pl-cogs-opex-url}}","description":"<p>Part of <strong>Bid Modelling</strong>.</p>\n<p>This endpoint extracts COGS and Opex line items for P&amp;L for building Bid Model.</p>\n<h4 id=\"request-body\">Request Body</h4>\n<ul>\n<li><p><code>input_urls</code> (array of strings, required): The URLs of the files that should be used as input. It can be any URL that ProductMind can handle. (e.g. excel, csv uploaded to Google Drive). At least 1 input file is required.</p>\n</li>\n<li><p><code>company_name</code> (string, required): The name of the company for which the analysis is done.</p>\n</li>\n<li><p><code>context</code> (string, optiona): Optional additional context that will be passed to the prompts. (e.g. an unusual financial year structure)</p>\n</li>\n<li><p><code>prompt_label</code> (string, optional): The label of the prompt that should be used from LangFuse. When it's missing the production version of the prompt will be used.</p>\n</li>\n<li><p><code>revenue_line_items</code> (string, optional): Optional but very much recommended. Revenue line items extracted in a previous step. Can be a markdown table, csv (as string), or json (as string)</p>\n</li>\n<li><p><code>initial_data_analysis</code> (string, optional): If analysis of the structure of the available data was already performed then it can be provided here in markdown format.</p>\n</li>\n<li><p><code>llm_model</code> (string, optional): Which LLM model to use during analysis. Possible values:</p>\n<ul>\n<li><p><code>claude-3-5-sonnet</code> (default)</p>\n</li>\n<li><p><code>gpt-4o</code></p>\n</li>\n<li><p><code>o1</code></p>\n</li>\n</ul>\n</li>\n<li><p><code>model_parameters</code> (object, optional): Optional parameters to the LLM model. For example <code>{ \"reasoning_effort\": \"high\" }</code> for o1, or <code>{\"temperature\": 0.5}</code> for Sonnet</p>\n</li>\n<li><p><code>return_mode</code> (string, optional): Controls how to return the results. Possible values:</p>\n<ul>\n<li><p><code>direct</code> (default): returns JSON</p>\n</li>\n<li><p><code>s3_url</code> : returns an S3 url as a combination of bucket + key to the json file (using this will require access to the S3 bucket)</p>\n</li>\n<li><p><code>s3_presigned_url</code> : returns a presigned S3 url valid for 1h to the json file (doesn't require access to the bucket to download the file)</p>\n</li>\n</ul>\n</li>\n</ul>\n<p>Note that when converting the input url the <code>optimize_for_tool_use</code> option will be used from the Convert endpoint, meaning some Python tool friendly source formats (e.g. Excel, Google Sheet, CSV) will not be converted to markdown, but rather be used as is. Other files will be converted first to markdown.</p>\n<h4 id=\"response\">Response</h4>\n<p>The response to this request will have a status code of 200 and a content type of application/json. The response body will include the following fields:</p>\n<ul>\n<li><p>cogs_line_items (array): An array of COGS (Cost of Goods Sold) line items, each containing accountName, accountType, amount, quarters, period, source, and translation_comments.</p>\n</li>\n<li><p>opex_line_items (array): An array of OPEX (Operating Expenses) line items, each containing accountName, accountType, amount, quarters, period, source, and translation_comments.</p>\n</li>\n<li><p>plan (string): The detailed plan that was used to extract the line items (for debug purposes).</p>\n</li>\n<li><p>analysis (string): The detailed analysis conducted before the extraction (for debug purposes).</p>\n</li>\n</ul>\n","urlObject":{"host":["{{bid-model-pl-cogs-opex-url}}"],"query":[],"variable":[]}},"response":[{"id":"3bf2e27a-e366-4080-b1f5-668175743d34","name":"[P&L] Extract COGS + Opex line items","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"input_urls\": [\n        \"https://docs.google.com/spreadsheets/d/1X919Dg8QnKt8aFtMJQRcJ8r_hCqfISi5-zzTUOLiLcg/edit?usp=drive_link\",\n        \"https://docs.google.com/spreadsheets/d/1Fw9Bhk3mCJiLcT_Q7-7jS0WvOSfEZM6jLxIQBC30kQw/edit?usp=drive_link\"\n    ],\n    \"company_name\": \"InMoment\",\n    \"context\": \"n.a.\",\n    \"prompt_label\": \"json\"\n}","options":{"raw":{"language":"json"}}},"url":"{{bid-model-pl-cogs-opex-url}}"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Date","value":"Tue, 28 Jan 2025 10:48:52 GMT"},{"key":"Content-Type","value":"application/json"},{"key":"Content-Length","value":"4678"},{"key":"Connection","value":"keep-alive"},{"key":"x-amzn-RequestId","value":"a06cb3e5-19e8-4087-998d-a9f2f68d661b"},{"key":"X-Amzn-Trace-Id","value":"Root=1-6798b54a-0a6618224eb4576a42a8fe96;Sampled=1;Lineage=1:4012f0cf:0"}],"cookie":[],"responseTime":null,"body":"{\n    \"cogs_line_items\": [\n        {\n            \"accountName\": \"Recurring Revenue FTE COGS\",\n            \"accountType\": \"(C) Software COGS\",\n            \"amount\": 14220.133,\n            \"quarters\": 3,\n            \"period\": \"Q1-Q3 FY24\",\n            \"source\": {\n                \"document\": \"FY24 Income Statement\",\n                \"page\": \"Income Statement\",\n                \"column\": \"Q1-Q3 FY24\",\n                \"row\": \"COST OF REVENUES\"\n            },\n            \"translation_comments\": \"FTE related costs for recurring revenue stream, calculated based on FY23 proportions\"\n        },\n        {\n            \"accountName\": \"Non-Recurring Revenue FTE COGS\",\n            \"accountType\": \"(C) Services COGS\",\n            \"amount\": 4027.913,\n            \"quarters\": 3,\n            \"period\": \"Q1-Q3 FY24\",\n            \"source\": {\n                \"document\": \"FY24 Income Statement\",\n                \"page\": \"Income Statement\",\n                \"column\": \"Q1-Q3 FY24\",\n                \"row\": \"COST OF REVENUES\"\n            },\n            \"translation_comments\": \"FTE related costs for non-recurring revenue stream, calculated based on FY23 proportions\"\n        },\n        {\n            \"accountName\": \"Hosting and Data Center\",\n            \"accountType\": \"(C) Software COGS\",\n            \"amount\": 6987.67,\n            \"quarters\": 3,\n            \"period\": \"Q1-Q3 FY24\",\n            \"source\": {\n                \"document\": \"FY23 Gross Margin Summary\",\n                \"page\": \"Gross Margin Summary FY23\",\n                \"column\": \"Recurring Revenue\",\n                \"row\": \"Application hosting and data center\"\n            },\n            \"translation_comments\": \"Hosting costs allocated based on FY23 proportions\"\n        },\n        {\n            \"accountName\": \"Software Licenses\",\n            \"accountType\": \"(C) Hard COGS License\",\n            \"amount\": 2195.608,\n            \"quarters\": 3,\n            \"period\": \"Q1-Q3 FY24\",\n            \"source\": {\n                \"document\": \"FY23 Gross Margin Summary\",\n                \"page\": \"Gross Margin Summary FY23\",\n                \"column\": \"Recurring Revenue\",\n                \"row\": \"Software Subscription / License\"\n            },\n            \"translation_comments\": \"Third-party software licenses based on FY23 proportions\"\n        }\n    ],\n    \"opex_line_items\": [\n        {\n            \"accountName\": \"Sales and Marketing\",\n            \"accountType\": \"(E) Sales & Marketing\",\n            \"amount\": 50445.576,\n            \"quarters\": 3,\n            \"period\": \"Q1-Q3 FY24\",\n            \"source\": {\n                \"document\": \"FY24 Income Statement\",\n                \"page\": \"Income Statement\",\n                \"column\": \"Q1-Q3 FY24\",\n                \"row\": \"Sales and marketing\"\n            },\n            \"translation_comments\": \"Direct from Income Statement\"\n        },\n        {\n            \"accountName\": \"General and Administrative\",\n            \"accountType\": \"(E) General & Administrative\",\n            \"amount\": 21082.942,\n            \"quarters\": 3,\n            \"period\": \"Q1-Q3 FY24\",\n            \"source\": {\n                \"document\": \"FY24 Income Statement\",\n                \"page\": \"Income Statement\",\n                \"column\": \"Q1-Q3 FY24\",\n                \"row\": \"General and administrative\"\n            },\n            \"translation_comments\": \"Direct from Income Statement\"\n        },\n        {\n            \"accountName\": \"Research and Development\",\n            \"accountType\": \"(E) Research & Development\",\n            \"amount\": 29772.879,\n            \"quarters\": 3,\n            \"period\": \"Q1-Q3 FY24\",\n            \"source\": {\n                \"document\": \"FY24 Income Statement\",\n                \"page\": \"Income Statement\",\n                \"column\": \"Q1-Q3 FY24\",\n                \"row\": \"Research and development\"\n            },\n            \"translation_comments\": \"Direct from Income Statement\"\n        },\n        {\n            \"accountName\": \"Interest Expense\",\n            \"accountType\": \"(O) Interest & Other\",\n            \"amount\": -24882.621,\n            \"quarters\": 3,\n            \"period\": \"Q1-Q3 FY24\",\n            \"source\": {\n                \"document\": \"FY24 Income Statement\",\n                \"page\": \"Income Statement\",\n                \"column\": \"Q1-Q3 FY24\",\n                \"row\": \"Interest expense\"\n            },\n            \"translation_comments\": \"Direct from Income Statement, negative as per guidance for Interest & Other expenses\"\n        }\n    ],\n    \"plan\": \"# Data Extraction Plan\\n\\n1. Time Period Selection\\n- Use FY24 Q1-Q3 (9 months ending August 31, 2024) as the primary period\\n- Use FY23 data for proportional calculations where needed\\n\\n2. COGS Extraction\\na) FTE Related COGS\\n- Calculate proportion of FTE COGS between Recurring and Non-Recurring from FY23\\n- Apply these proportions to FY24 total COGS\\n\\nb) Non-FTE COGS\\n- Use the detailed breakdown from FY23 to calculate proportions\\n- Apply these proportions to FY24 Q1-Q3 total COGS\\n\\n3. Opex Extraction\\n- Direct extraction from FY24 Income Statement\\n- Sum Q1-Q3 values for each line item\\n- Ensure proper categorization as per guidance\\n\\n4. Verification Steps\\n- Cross-check totals against Income Statement\\n- Verify all revenue streams have corresponding COGS\\n- Ensure no double-counting in breakdowns\\n\",\n    \"analysis\": \"# Initial Data Analysis\\n\\n1. File Structure Analysis\\n- FY24 file contains recent Income Statement (Q1-Q3)\\n- FY23 file contains detailed Gross Margin Summary\\n- Both files provide quarterly breakdowns\\n\\n2. Data Quality Assessment\\n- FY24 data is more recent but less detailed\\n- FY23 data provides detailed COGS breakdown\\n- Consistent structure between periods\\n- No missing quarters in the analyzed period\\n\\n3. Revenue Stream Analysis\\n- Clear separation between Recurring and Non-Recurring\\n- Consistent categorization across periods\\n- Detailed COGS allocation visible in FY23\\n\\n4. COGS Structure\\n- Two-level structure: FTE and Non-FTE\\n- Clear allocation between revenue streams\\n- Consistent categorization possible\\n\\n5. Opex Structure\\n- Standard categories present\\n- Clear quarterly progression\\n- No unusual items or categorization issues\\n\"\n}"}],"_postman_id":"80c97ff5-a636-4007-a2ca-a1cd04e33829"}],"id":"1a70c6ac-3032-45bf-bf94-1e61369cf933","description":"<p>Within this folder are APIs that can be used to prepare data for various portions of the Bid Model.</p>\n<p>One important step that we found when working with these APIs is to clean the input data. Here is a document describing the recommended data cleaning steps that will allow the LLMs to extract data more correctly: <a href=\"https://docs.google.com/document/d/1S3DvS-2iSDk7dYYMV709-KcVnRazMcqDtFPzlYTNoaY/edit?usp=sharing\">https://docs.google.com/document/d/1S3DvS-2iSDk7dYYMV709-KcVnRazMcqDtFPzlYTNoaY/edit?usp=sharing</a></p>\n","_postman_id":"1a70c6ac-3032-45bf-bf94-1e61369cf933"}],"event":[{"listen":"prerequest","script":{"id":"c1c449ee-2c71-4da4-8b23-dc6ce62763bd","type":"text/javascript","packages":{},"exec":[""]}},{"listen":"test","script":{"id":"2688850d-ba1b-40c4-b2a8-2a7e6674013a","type":"text/javascript","packages":{},"exec":[""]}}],"variable":[{"key":"api-gw-url","value":"productmind.trilogy.com"},{"key":"video-extract-auth-token","value":"","type":"default"}]}