Reference

Source code


<?xml version="1.0" encoding="utf-8"?>
<ApiConfig Name="ServiceNow"
           Desc="Read and write ServiceNow data effortlessly. Integrate, manage, and automate incidents, tasks, attachments, and records — almost no coding required."
           Slug="servicenow-connector" Id="17205e73-c22f-4d57-a9d4-db295d46bdb3"
           Logo="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJYAAACGCAMAAAAICYNLAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAALoUExURQAAAGLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTmLYTv///9y1J+8AAAD2dFJOUwAAAxEnQmF/m7TI2OXu8vX29O/n3Mu3oIJkRikTBAsoTnunyeHx+vviqlINBiVWjsHm6MSRVwgvbrLk/ONvMAJq6uu2ayYOSZ2fGL/AZhkdddD90R5y1dZ0Gg/Oz0e6RSGT8JIgBdJYlZjKzArsni6+QNRTX2ABZVQtG7wJcR/NmZZbI49IQxC92Wf+xppwNiRP4KV387lou9McefixB7X5XAwXYmxN9z/Dbbgx3zg5WrOJjBbFSpAqg4hRK32XfKg8QaYSx+0yXj4i2q+cioeN3hSkUOmLczcV3Sw1o2miPa40TKE7dtvCRIB4sF2p13qrgTqsWSOp7WMAAAABYktHRPer3Hr3AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH5wYBEBwcHjmxPQAACY1JREFUeNrFnGtAVMcVgO9ZEGkioKgrK4LEsAvy0IBC1LVuoJUoBjRgUEEkJTyiiDQlKkaQGKJriqAxJZGEImIwscRHlEi19uEzqdpUl9iUGGtia2rTJjHVzu/OZVlgl32cmTu7nJ9w5pxv586dxzlnriRxCZhF5eU9zGe47w8eeHCEn3/AyFGBo8eMVY8L0owPnhDSq8Jnn58pdGLYQ5MeDtfqyCCJ8I8cO3l4VHC058h6HMXETpn6SJwdICu4+GnTE2JjPEDW4yLx0RkzZ+kJSvSzZ/5wTqJ7yWTjhtjH1Ek4JIsk/+jHcw1uA5MNpzw+L5yNySyR8x9PcQuYbDRVs2AkD5QsI59ISxcOJhtcuOjJDF4oWTIyFy0WCiYbS38qSwmTWZYsXSYMTDaUrclRDiXLck22GDB5Ls9dESGGik5mK/JUyrnkn/b0T7SioGTJf6ZAaYfR5oUJRSKhZCkqLlTEJb9/zwaIpqKzxcrF/FxyV+etEg8lS0ku74OkzVYvTXYPFSGlS1dzcdFGy9YIewEHS8SaZRxctEnZT90HJcuCMmYu2uC5n7mXipCsYYxcVD0q0t1UhMwuZ+Kiys+7bbAPlOS16/BcAOvWB3qCik75aWguSpUmdLlxJtr1yOdI1dbme4qKkMDnUVxUqdwj48oipRUILqoybLYnqej76HqeoAqPZnmWis5fG1xxAbzwhKepCNmY7hyLrs7jPE9FiG+lMy7al4uQx2WxElHl5DHSf+WWDgUVne7zHHMBbKoeGipCxi52hAUQ8+JQURGyudA+F+3Fl7jP8solIMH+YwSoyRo6KkIyN9nDoqfUZ4eSipCXDXa4ALZ4bNtgXwK3DsYCMG7jt6jTjngls6Qk85UR9kKpWFGnDOIC+DnfRFqbtL2uPmzHzvQJRuOE9Ngdr1b5bmcMF1okwscWi66FmTxMu17TbEgBG0kpWz8pvJbDXEmqDRfAL9itNLyeVqOyjXH3Bux3vrF7FPuvrLLGAih4kNWGdlLeagchZHPcPndyA6vNxjetzAG8xWig6Zd5MeB8fYXmLXtaGM3WW3f8C4xn1aK9q13FNuT/t/osYbObs2+AUYDHmEZok+/TmICLrLNznI7Fsv7tfrN0zprG0nZEWjP+FJXYFs9ie1trn2WA/e8wtFz+Lj421RMjYxkgAbn9WAaWnfK2YNbAQdkBBvPzVWBp6M0QBnl9E3uYpWY33v5s717zAG0MfVXAE5QqYAiV/cqCValGt1k1ly+E5z0W7aK9EsyN3kMf7g8e4g14Ht6F9ZH8Xo8LgCpsi4Zi/vDwEfQSaZ7pofl9bIOjKt5oOl28j2G9vN8McoNYbCjkQAd/7gEg9QOkm1mx1A1AAnL/l5+rICVCmx5Hbsr1CT1Y05G/YjP3IzRzhdQhHXXKWNHIzt31a6VprQ3I0TItmmIFI5fSE8qzbSdxnkZPpFi/wWVQwicqTU4CnJqFcqV7lWL9FvcTpivOmQKs+x3O1+9BUv0BpZl/WnmGGeAMbnd/ViWdw2UMN4aKwIp+BOXsvJcUjNvUPCUmHY87yYR7S3n+GMULH4rBOoRKRGi3ShrUiyhPJQIEjKgho/ORTqC6tVNMrQfASpS74dJ8jFrtR6Kw0lBYdZIa9bB3iML6I2rbNVNC7WbHvCmokAguol787dIljNoHraKwjKgQ+xIpDqN2OUQUVnM7xl+k5IdR+5OoajAwnMX4S5JQQ3CqMCxAZSTyJVRlz0lxWJ0Yfw0ex/oY42+UhNpq/Fkc1lGMP38JVfBwTBzWFYw/Pwm1k98sDgu1KMZJVzFqZw3CJgjUZniM9CRGbXeiKKxKVAonR0JFnopMorA6UBHLjdIkjFp8sCisU6h8UJeEejNajova2ITpMP4+lmag6qffEoWFOpXq26RPUPnpy4VisGJQsbSA/dKH1zCKVwvEnHxqULcARs+R0lGvRsQUMVhHULG0olSpeQ9GkcwXMaGCqgvlbGazBFNRmrtiRRz25+KO8H8BCXxQmqRKBNanKFf0+CfBX3EhzVUm5YGkblzSIH8HYJcDq0wfL5YGFzxu7KZYKtTyQ8gD3UqDlB3IKvcugxxpnoFTrq1XeiXgU2SKt60nAI4L7hDymaJQM8B11NaOkMDPZT9gfBinTm4kKkkXVKJOiFTOZ5tTUdhsTEsa92OkDf+mQ7o52psh24LNVEce5s+QncYFvwkZOb4Xqxu1ce7pX/bcay9VDfquSXXvBIl/inSDY+LLvu5DJwf7jsoAz+GLYW6e48lVn8MOd0K0X/RhtS5AtyI3u9kz+9038Pb7EwBMqX3yJduNJqq86TLeeu0bA6pGLn7GwHXgFlvVyOcslTKXBtRTAnLT1StX94bga2wKPzrIYvuoVUXSLaYLBQGb0RVJF1cyldjGz7HCUqHC8/3SuLYVU78V/XYWm906q9pTOgmjYqj90rLn745K8CxMEBqm1rFZLT1kU4QX8g82A/RJ7plisn8n3/xXU7GauUTa1yZLT7c37NdVWqqDbmdbqjoHEgFk3z5RzdhTVOJvDSrwNDzDbIWK9vyVilNelo8s9EjIuVMVV85zFSIfG3RFCiAYuUuzlYhrOV92fqUprigvryjWfNV5Oeca57XGfw4+9MnXMHgKa/skI0Ovz1B2Tb3e7jg13VFiVLls87JfWostgnGP+P3Lwe0CFbbaxi1y0mB/EgRYiC+VEy7TUh1MzXItk4duSw6W5GFOVox1X/O+jbV6XVOTTs/bPOPfTsu2jf9hNahLKlLXBbV9E3V8/PjjUd+0Bfm2NybpWK18G+1k3afEExsZjAV8N/nu/uumZuvLBc2m62EPff8dy4JYXeN0NyLfIkPFUqnk3/nv1nSV9ZLYvyiq0rcGHcDeVY0743qTlIb5mXSVvufkmz7m/0TfO1GNqeNvcH39lS61QS6jUIH3o0wuP5lj3t2U33f5cuvuGjA73VAXubXSeadxXxgyj7Qv1ji/XFj7MibiQi15vebEiv/Nwyq2k4/q3g1nVU/zUlDGqKGO7x3Z0K/ILWT7wISsHbNlo8OB0YU9psvf97lv38bVNo7vvcgtjDMcHMu6JrD0fIe95xjx7Qa+T3HIrcom29scjsNTmcfX9CZbE3H1oUrCbqFVo20tvjPVyDogYtZmWXdV+20ln5+R295u11mZLNrL+uEY2UrB3eV9YUK/9pdSlFfpphxRX7BYDChZtJDjd8pNlv1v5ao4bfKl9qAzLg/ROIut737dfunahYN3Oj/Z58zi/wHJ99FRQvowYgAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMy0wNi0wMVQxNjoyODoxMyswMDowMI1DjK0AAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjMtMDYtMDFUMTY6Mjg6MTMrMDA6MDD8HjQRAAAAKHRFWHRkYXRlOnRpbWVzdGFtcAAyMDIzLTA2LTAxVDE2OjI4OjI4KzAwOjAwJ4NG1wAAAABJRU5ErkJggg=="
           Version="4" 
		   EngineVersion="20">
    <VersionHistory>
		<Change Ver="3" Date="2026-01-23" Type="New">Added two new OAuth connection types (e.g. Client Credentials Grant, User Credentials Grant).</Change>
		<Change Ver="3" Date="2026-01-23" Type="New">Added new option DateTimeValueHandling at connection level and EndPoint level (e.g. for get_table_rows) to treat DateTime as DateTime2 (Useful for Gateway to avoid - Error converting data type DBTYPE_DBTIMESTAMP to datetime).</Change>		
		<Change Ver="3" Date="2026-01-23" Type="Fix">Changed test connection to use sys_user rather than sys_properties incase that table is locked down.</Change>
		<Change Ver="3" Date="2026-01-23" Type="Fix">Resolved an issue with get_table_rows endpoint where queries with selected fields returned zero results due to an incorrect parameter separator ('&amp;') instead of a comma.</Change>
		<Change Ver="3" Date="2026-01-23" Type="New">Added new endpoint get_record_labels to retrieve UI labels (tags) for a specific parent table record with optional filtering.</Change>
		<Change Ver="3" Date="2026-01-23" Type="New">Added a new endpoint get_table_row_count to get row count for a specified table or filter expression (query).</Change>	
		<Change Ver="3" Date="2026-01-23" Type="New">Automatically map large text fields (including html and journal fields) to DT_NTEXT instead of DT_WSTR, even when max_length is reported as 4000, to prevent truncation of fields such as description and comments.</Change>
		<Change Ver="3" Date="2026-01-23" Type="New">Use system defined length from metadata (i.e. max_length) rather than fixed 2000 chars for all string column.</Change>
		<Change Ver="3" Date="2026-01-23" Type="New">Added new parameter AllowDisplayValueAsInput (Useful for Insert/Update operation. With this you can supply Label rather than Id for reference / lookup field value).</Change>		
		<Change Ver="3" Date="2026-01-23" Type="New">Added five new attachment-related endpoints: get_attachments (retrieve attachment metadata with filters), download_attachments (bulk download attachments to a folder), download_attachments_by_parent_search (download attachments based on parent record search), get_attachments_by_parent_search (retrieve attachment metadata by parent search), and download_attachment (download a single attachment with custom file path).</Change>
		<Change Ver="3" Date="2026-01-23" Type="New">Added ExpandContinueOnError to continue listing EndPoints / Tables if user doesnt have List Table permission.</Change>
		<Change Ver="3" Date="2026-01-23" Type="New">Added clear error message if instance name is invalid / reclaimed.</Change>
        
		<Change Ver="2" Date="2024-11-29" Type="New">Added images in HTTP and OAuth authentication instructions</Change>
        <Change Ver="1" Date="2023-09-01" Type="New">Add new options Query and Fields for Read Data operation (get_table_rows).</Change>
        <Change Ver="1" Date="2023-09-01" Type="Fix">Make ApiVersion optional.</Change>
        <Change Ver="1" Date="2023-09-01" Type="Fix">Using Basic Auth throws error - Input string was not in a correct format.</Change>
        <Change Ver="1" Date="2023-09-01" Type="Fix">Test connection always works</Change>
        <Change Ver="1" Date="2023-03-15" Type="New">Initial version</Change>
    </VersionHistory>

    <ServiceUrls>
        <ServiceUrl Name="ServiceNow API" Url="https://[$InstanceName$].service-now.com/api/now" />
    </ServiceUrls>

    <Auths>
	
<Auth Type="HTTP" Name="BasicAuth" Label="Basic Auth (UserName and Password)"
              Desc="Authenticate using ServiceNow instance username and password."
              ConnStr="CredentialType=Basic;UserName=[$UserName$];Password=[$Password$];RetryMode=[$RetryMode$];RetryCountMax=[$RetryCountMax$];RetryMultiplyWaitTime=[$RetryMultiplyWaitTime$];RetryStatusCodeList=[$RetryStatusCodeList$];"
              TestEndPoint="test_connection" TestParser="True">
            <Params>
                <Param Name="InstanceName" Label="InstanceName (e.g. mycompany)" Required="True" Desc="Check your instance URL, if it says https://mycompany.service-now.com then enter mycompany as InstanceName."/>
                <Param Name="UserName" Label="User name" Required="True"
                       Desc="You can create new user account and set password here https://{your-instance-id}.service-now.com/now/nav/ui/classic/params/target/sys_user.do or visit All \ Organization \ Users in the portal" />
                <Param Name="Password" Required="True" Secret="True"
                       Desc="You can create new user account and set password here https://{your-instance-id}.service-now.com/now/nav/ui/classic/params/target/sys_user.do or visit All \ Organization \ Users in the portal" />
                <Param Name="ApiVersion" Value="v2" Options="Default=;v2=v2;v1=v1" ValueTemplate="{$value$}/" />

                <!--below not exposed as root level property in HTTP Connection so use as placeholder-->
                <Param Name="RetryMode" Value="RetryWhenStatusCodeMatch"
                       Options="None;RetryAny;RetryWhenStatusCodeMatch;" Hidden="True" />
                <Param Name="RetryStatusCodeList" Value="429" Hidden="True" />
                <Param Name="RetryCountMax" Value="5" Hidden="True" />
                <Param Name="RetryMultiplyWaitTime" Value="True" Hidden="True" />
				
				<Param Name="DateTimeValueHandling" Label="Date Time Value Handling" Hidden="False" Options=";Use datetime2 for DateTime values (avoids conversion errors)=TreatAsDateTime2;Treat DateTime values as string=TreatAsString"/>

            </Params>
            <Notes>
                <![CDATA[
<p>Locate your ServiceNow instance credentials and use them for HTTP authentication:</p>
<ol>
    <li>Go to <a href="https://developer.servicenow.com/dev.do" target="_blank">https://developer.servicenow.com/dev.do</a> and log in.</li>
    <li>Click on your profile picture.</li>
    <li>
        <p>When a menu appears, click on <strong>Manage instance password</strong> or a similar option:</p>
        <img src="https://cdn.zappysys.com/api/images/authentication/service-now/http/manage-instance-password-in-service-now.png" 
                loading="lazy" 
                decoding="async" 
                class="img-thumbnail" 
                alt="Manage instance password in ServiceNow" 
                title="Managing instance password in ServiceNow" 
                width="1002" 
                height="543" />
    </li>
    <li>
        <p>In a new window you will see your HTTP Basic Authentication credentials:</p>
        <img src="https://cdn.zappysys.com/api/images/authentication/service-now/http/use-instance-credentials-to-authenticate-to-service-now.png" 
                loading="lazy" 
                decoding="async" 
                class="img-thumbnail" 
                alt="Use instance credentials to authenticate to ServiceNow" 
                title="Using instance credentials to authenticate to ServiceNow"
                width="990" 
                height="443" />
    </li>
    <li>
        <p>Done! Use this <strong>username</strong> and <strong>password</strong> when configuring <em>HTTP Authentication</em> parameters.</p>
    </li>
</ol>
]]>
            </Notes>
        </Auth>
		
		<Auth Name="OAuthCode" Template="OAuthTemplate" Type="OAuth" Label="OAuth Authorization Code Grant (User Creds)"
			  Desc="Authenticate using OAuth 2.0 Authorization Code Flow (3-legged)"
			  ConnStr="Provider=Custom;OAuthVersion=OAuth2;GrantType=AuthorizationCode;AuthorizeInFullBrowser=True;ExtraAttributesForTokenRequest=redirect_uri=[$RedirectUri$];AuthUrl=https://[$InstanceName$].service-now.com/oauth_auth.do;TokenUrl=https://[$InstanceName$].service-now.com/oauth_token.do;TokenUrl=https://[$InstanceName$].service-now.com/oauth_token.do;ClientId=[$ClientId$];ClientSecret=[$ClientSecret$];ReturnUrl=[$RedirectUri$];AuthorizationUrl=https://[$InstanceName$].service-now.com/oauth_auth.do"
			  TestEndPoint="test_connection" TestParser="True">
			<Params>
				<Param Name="RedirectUri" Label="Redirect URI (***Must match as App Registry Page***)" Required="True" Value="https://zappysys.com/oauth" />
			</Params>
		</Auth>	
		
		<Auth Name="OAuthClientCreds" Template="OAuthTemplate" Type="OAuth"  Label="OAuth Client Credentials Grant (Must be enabled by Admin)"
			  Desc="Authenticate using OAuth Client Credentials Grant (Client ID and Client Secret)."
			  HelpLink="https://support.servicenow.com/kb?id=kb_article_view&amp;sysparm_article=KB0778194"
			  ConnStr="Provider=Custom;OAuthVersion=OAuth2;GrantType=ClientCredentials;TokenUrl=https://[$InstanceName$].service-now.com/oauth_token.do;ClientId=[$ClientId$];ClientSecret=[$ClientSecret$]"
			  TestEndPoint="test_connection" TestParser="True">
			<Params>

			</Params>
		</Auth>
		
        <Auth Name="OAuth" Template="OAuthTemplate" Type="OAuth" Label="OAuth Password Grant"
              Desc="Authenticate using OAuth Password Grant (ServiceNow instance username, password, OAuth Client ID, and Client Secret)."
              HelpLink="https://support.servicenow.com/kb?id=kb_article_view&amp;sysparm_article=KB0778194"
              ConnStr="Provider=Custom;OAuthVersion=OAuth2;GrantType=Password;TokenUrl=https://[$InstanceName$].service-now.com/oauth_token.do;Username=[$UserName$];Password=[$Password$]"
              TestEndPoint="test_connection" TestParser="True">

            <Params>
                <Param Name="UserName" Label="User name" Required="True"
                       Desc="You can create new user account and set password here https://{your-instance-id}.service-now.com/now/nav/ui/classic/params/target/sys_user.do or visit All \ Organization \ Users in the portal" />
                <Param Name="Password" Required="True" Secret="True"
                       Desc="You can create new user account and set password here https://{your-instance-id}.service-now.com/now/nav/ui/classic/params/target/sys_user.do or visit All \ Organization \ Users in the portal" />
            </Params>
        </Auth>		
    </Auths>


    <Template>
		<Auth Name="OAuthTemplate">
			<Params>
				<Param Name="InstanceName" Label="InstanceName (e.g. mycompany)" Required="True" />
				<Param Name="ClientId" Label="Client ID" Required="True" />
				<Param Name="ClientSecret" Label="Client Secret" Required="True" Secret="True" />

				<Param Name="ApiVersion" Required="True" Value="v2" Options="Default=;v2=v2;v1=v1" ValueTemplate="{$value$}/" />
				<Param Name="RetryMode" Value="RetryWhenStatusCodeMatch" Options="None;RetryAny;RetryWhenStatusCodeMatch;" Hidden="True" />
				<Param Name="RetryStatusCodeList" Value="429|503" Hidden="True" />
				<Param Name="RetryCountMax" Value="5" Hidden="True" />
				<Param Name="RetryMultiplyWaitTime" Value="True" Hidden="True" />
				<Param Name="DateTimeValueHandling" Label="Date Time Value Handling" Hidden="False" Options=";Use datetime2 for DateTime values (avoids conversion errors)=TreatAsDateTime2;Treat DateTime values as string=TreatAsString"/>
				
				
			</Params>
			<Notes>
				<![CDATA[ 
<p>Create OAuth application and use it for authentication:</p>
<ol>
    <li>Login to your instance at <span style="text-decoration: underline">https://<strong>your-instance-id</strong>.service-now.com</span>.</li>	
    <li>
        <p>Start by clicking on menu item <strong>All</strong>, then search for <strong>oauth</strong>, and click <strong>Application Registry</strong> option:</p>
        <img src="https://cdn.zappysys.com/api/images/authentication/service-now/oauth/locate-oauth-configuration-in-service-now.png" 
                loading="lazy" 
                decoding="async" 
                class="img-thumbnail" 
                alt="Locate OAuth configuration in ServiceNow" 
                title="Locating OAuth configuration in ServiceNow" 
                width="1000" 
                height="376" />
    </li>
    <li>
        <p>Then click button <strong>New</strong>:</p>
        <img src="https://cdn.zappysys.com/api/images/authentication/service-now/oauth/create-new-oauth-application-in-service-now.png" 
                loading="lazy" 
                decoding="async" 
                class="img-thumbnail" 
                alt="Create new OAuth application in ServiceNow" 
                title="Creating a new OAuth application in ServiceNow" 
                width="1002" 
                height="303" />
    </li>
    <li>
        <p>Continue by clicking <strong>Create an OAuth API endpoint for external clients</strong> option:</p>
        <img src="https://cdn.zappysys.com/api/images/authentication/service-now/oauth/use-service-now-oauth-application-for-external-clients.png" 
                loading="lazy" 
                decoding="async" 
                class="img-thumbnail" 
                alt="Use ServiceNow OAuth application for external clients" 
                title="Using ServiceNow OAuth application for external clients" 
                width="1002" 
                height="307" />
    </li>
    <li>
        <p>Move on by naming your OAuth application and entering a Client Secret (or let it be generated automatically).</p>
    </li>
	<li>Click on the lock icon next to the Redirect URL. Enter <code>https://zappysys.com/oauth</code>. This is not needed if you use <b>Client Credentials Grant</b> or <b>Password Grant</b></li>	
    <li>
        <p>Finally give it a final touch by increasing the <strong>Refresh Token Lifespan</strong> value to <code>315,360,000</code> (it should last for 10 years):</p>
        <img src="https://cdn.zappysys.com/api/images/authentication/service-now/oauth/configure-oauth-application-in-service-now.png" 
                loading="lazy" 
                decoding="async" 
                class="img-thumbnail" 
                alt="Configure OAuth application in ServiceNow" 
                title="Configuring OAuth application in ServiceNow" 
                width="1002" 
                height="435" />
    </li>
	<li>Change Default Grant Type as per your need. <div><b>NOTE:</b> If you prefer to use Client Credentials grant (Service account style access without using real userid-password) then your admin must enable it. Client Credentials is only supported on instances where it is explicitly enabled by the ServiceNow administrator. Its not supported in Dev / Free instance.
	</div></li>
    <li>
        <p>Done! Now you can use <strong>Client ID</strong> and <strong>Client Secret</strong> when configuring <em>OAuth Authentication</em> parameters.</p>
    </li>
</ol>

<h3>Enable Client Credentials Grant Type</h3>
<ul>
  <li>
    <strong>Enable the Client Credentials Grant Type:</strong>
    Go to <em>System Properties &gt; All Properties</em>, create a new property named <code>glide.oauth.inbound.client.credential.grant_type.enabled</code>, and set it to <strong>true</strong>.
  </li>
  <li>
    <strong>Configure the OAuth Application:</strong>
    Navigate to <em>System OAuth &gt; Application Registry</em>, click <strong>New</strong>, and select <strong>Create an OAuth API endpoint for external clients</strong>. Set the name and save the record. In the <strong>Default Grant Type</strong> field, select <strong>Client Credentials</strong> and associate it with the integration user.
  </li>
</ul>
]]>
			</Notes>			
		</Auth>
		<Param Name="TmpAttachmentQuery"
			Label="Attachment Filter / Order By"
			ValueTemplate="^{$value$}"
			Options="Uploaded Today=sys_created_on&gt;=&lt;&lt;today,FUN_TO_DATETIME&gt;&gt;^sys_created_on&lt;=&lt;&lt;today|~|yyyy-MM-dd 23:59:59,FUN_TO_DATETIME&gt;&gt;;
			Uploaded Last 2 Days=sys_created_on&gt;=&lt;&lt;today-2d,FUN_TO_DATETIME&gt;&gt;;
			Uploaded After Date=sys_created_on&gt;=2026-01-01;
			File Name Equals=file_name=dump.png;
			File Name Starts With=file_nameSTARTSWITHdump;
			File Name Contains=file_nameLIKEerror;
			File Name Ends With=file_nameENDSWITH.pdf;
			Images Only=content_typeSTARTSWITHimage/;
			Larger Than 1MB=size_bytes&gt;1048576;
			Uploaded By User=sys_created_by=admin;
			Order By Created Date=ORDERBYsys_created_on;
			Order By Size Desc=ORDERBYDESCsize_bytes;"
			Desc="Server-side filter for sys_attachment (file name, size, type, date, parent record, etc.)"
            HelpLink="https://docs.servicenow.com/bundle/utah-platform-user-interface/page/use/common-ui-elements/reference/r_OpAvailableFiltersQueries.html" 
		/>			
			
        <EndPoint Name="TmpPagination">
            <Params>
                <Param Name="PagingRowCount" Label="Page Size (Default=2000, Max=10000)" Type="Query"
                       Key="sysparm_limit" Hidden="True" Required="True" Value="2000"
                       Desc="Max can be 10000 but it may decrease performance if you fetching less than 10K rows in some requests." />
                <Param Name="PagingMode" Type="Property" Value="ByResponseHeaderRfc5988" />
				<Param Name="PagingOffset" Type="Query" Key="sysparm_offset" Hidden="True" />
            </Params>
        </EndPoint>

        <EndPoint Name="TmpPaginationOffset">
            <Params>
                <Param Name="PagingRowCount" Label="Page Size (Default=2000, Max=10000)" Type="Query"
                       Key="sysparm_limit" Hidden="True" Required="True" Value="2000"
                       Desc="Max can be 10000 but it may decrease performance if you fetching less than 10K rows in some requests." />
                <Param Name="PagingOffset" Type="Query" Key="sysparm_offset" Hidden="True" Required="True" Value="0" />
                <Param Name="PagingMode" Type="Property" Value="ByUrlParameter" />
                <Param Name="PagingByUrlAttributeName" Type="Property" Value="sysparm_offset" />
                <Param Name="PagingIncrementBy" Type="Property" Value="2000"
                       Desc="This must match with PagingRowCount Value" />
                <Param Name="PagingByUrlEndStrategy" Type="Property" Required="True" Value="DetectBasedOnResponseSize" />
                <Param Name="PagingByUrlCheckResponseMaxBytes" Type="Property" Required="True" Value="20"
                       Desc="If Last response is less than 20 bytes stop. Last response is {result:[]}" />
                <Param Name="PagingByUrlCurrentPage" Type="Property" Value="0" />
            </Params>
        </EndPoint>

        <EndPoint Name="TmpTableOutputColumns">
            <OutputColumns>
                <Column Name="sys_id" DataType="DT_WSTR" Length="500" />
                <Column Name="name" DataType="DT_WSTR" Length="500" />
                <Column Name="label" DataType="DT_WSTR" Length="500" />
                <Column Name="sys_name" DataType="DT_WSTR" Length="500" />
                <Column Name="create_access" DataType="DT_WSTR" Length="50" />
                <Column Name="alter_access" DataType="DT_WSTR" Length="50" />
                <Column Name="access" DataType="DT_WSTR" Length="500" />
                <Column Name="live_feed_enabled" DataType="DT_WSTR" Length="50" />
                <Column Name="sys_updated_on" DataType="DT_DBTIMESTAMP" />
                <Column Name="sys_class_name" DataType="DT_WSTR" Length="500" />
                <Column Name="is_extendable" DataType="DT_WSTR" Length="50" />
                <Column Name="user_role" DataType="DT_WSTR" Length="500" />
                <Column Name="create_access_controls" DataType="DT_WSTR" Length="50" />
                <Column Name="delete_access" DataType="DT_WSTR" Length="50" />
                <Column Name="sys_updated_by" DataType="DT_WSTR" Length="100" />
                <Column Name="sys_class_path" DataType="DT_WSTR" Length="500" />
                <Column Name="sys_created_on" DataType="DT_DBTIMESTAMP" />
                <Column Name="caller_access" DataType="DT_WSTR" Length="500" />
                <Column Name="client_scripts_access" DataType="DT_WSTR" Length="50" />
                <Column Name="extension_model" DataType="DT_WSTR" Length="500" />
                <Column Name="actions_access" DataType="DT_WSTR" Length="50" />
                <Column Name="sys_scope.link" Label="sys_scope_link" DataType="DT_WSTR" Length="1000" />
                <Column Name="sys_scope.value" Label="sys_scope_value" DataType="DT_WSTR" Length="500" />
                <Column Name="sys_created_by" DataType="DT_WSTR" Length="100" />
                <Column Name="sys_class_code" DataType="DT_WSTR" Length="500" />
                <Column Name="read_access" DataType="DT_WSTR" Length="50" />
                <Column Name="super_class" DataType="DT_WSTR" Length="500" />
                <Column Name="sys_mod_count" DataType="DT_WSTR" Length="50" />
                <Column Name="ws_access" DataType="DT_WSTR" Length="50" />
                <Column Name="update_access" DataType="DT_WSTR" Length="50" />
                <Column Name="sys_package.link" Label="sys_package_link" DataType="DT_WSTR" Length="1000" />
                <Column Name="sys_package.value" Label="sys_package_value" DataType="DT_WSTR" Length="500" />
                <Column Name="sys_update_name" DataType="DT_WSTR" Length="500" />
                <Column Name="scriptable_table" DataType="DT_WSTR" Length="50" />
                <Column Name="configuration_access" DataType="DT_WSTR" Length="50" />
                <Column Name="number_ref" DataType="DT_WSTR" Length="500" />
                <Column Name="sys_policy" DataType="DT_WSTR" Length="500" />
                <Column Name="sys_scope" DataType="DT_WSTR" Length="500" />
                <Column Name="sys_package" DataType="DT_WSTR" Length="500" />
                <Column Name="super_class.link" Label="super_class_link" DataType="DT_WSTR" Length="1000" />
                <Column Name="super_class.value" Label="super_class_value" DataType="DT_WSTR" Length="500" />
                <Column Name="number_ref.link" Label="number_ref_link" DataType="DT_WSTR" Length="1000" />
                <Column Name="number_ref.value" Label="number_ref_value" DataType="DT_WSTR" Length="500" />
                <Column Name="user_role.link" Label="user_role_link" DataType="DT_WSTR" Length="1000" />
                <Column Name="user_role.value" Label="user_role_value" DataType="DT_WSTR" Length="500" />
            </OutputColumns>
        </EndPoint>

        <EndPoint Name="TmpDynamicTableInputColumns">
			<Params>
				<Param Name="AllowDisplayValueAsInput" Key="sysparm_input_display_value" Type="Query" Options=";true;false" Label="Allow Label as Input Value (Default: false - Use Id for reference field)"
					Desc="When AllowDisplayValueAsInput is enabled, ServiceNow may accept display values for reference fields, but the resolved value may be inconsistent across fields and instances. For deterministic behavior, always use sys_id values."
				/>
			</Params>
			
            <InputColumns>
                <Column Name="[$parent.Pivot_Name$]" DataType="DT_WSTR" Length="2000" Expand="True"
                        DataEndPoint="get_table_columns" DataEndPointParameters="TableName=[$TableName$];"
                        ColumnInfoMap="Length=Pivot_Value_max_length;DataType=Pivot_Value_internal_type|ntext=Pivot_Value_max_length(equals:4000)"
                        DataTypeMap="DT_BOOL=boolean;
                                     DT_NUMERIC=currency,price,float,decimal,percent_complete;
                                     DT_STR=currency2,domain_id,document_id,reference,audio,video,user_image,phone_number_e164,file_attachment,GUID;
                                     DT_DBTIMESTAMP=glide_date_time,calendar_date_time,due_date,glide_duration,insert_timestamp,glide_utc_time,glide_time;
                                     DT_DBDATE=glide_date;
									 DT_NTEXT=ntext,html,journal_list,journal_list,journal_input;
                                     DT_I4=integer;
                                     DT_I8=longint"
                        KeyIf="sys_id" />
            </InputColumns>
        </EndPoint>

        <EndPoint Name="TmpDynamicTableOutputColumns">
			<Params>
				<Param Name="DateTimeValueHandling" Label="Date Time Value Handling" Hidden="False" Type="Property" />
			</Params>
            <OutputColumns>
                <Column Name="sys_id" DataType="DT_WSTR" Length="32" />
				
                <Column Name="&lt;&lt;[$parent.Pivot_Value_internal_type$]|~|domain_id|document_id|reference|currency2|~|[$parent.Pivot_Name$].value|~|[$parent.Pivot_Name$],FUN_IF_REGEX_MATCH&gt;&gt;"
						Label="[$parent.Pivot_Name$]" DataType="DT_WSTR" Length="2000" Expand="True"
						DataEndPoint="get_table_columns" DataEndPointParameters="TableName=[$TableName$];DateTimeValueHandling=[$DateTimeValueHandling$]"
						ColumnInfoMap="Length=Pivot_Value_max_length;DataType=Pivot_Value_internal_type|ntext=Pivot_Value_max_length(equals:4000)"
						DataTypeMap="DT_BOOL=boolean;
                                   DT_NUMERIC=currency,price,float,decimal,percent_complete;
                                   DT_STR=currency2,domain_id,document_id,reference,audio,video,user_image,phone_number_e164,file_attachment,GUID;
                                   DT_DBTIMESTAMP=glide_date_time,calendar_date_time,due_date,glide_duration,insert_timestamp,glide_utc_time,glide_time;
                                   DT_DBDATE=glide_date;
								   DT_NTEXT=ntext,html,journal_list,journal_list,journal_input;
                                   DT_I4=integer;
                                   DT_I8=longint"
                    KeyIf="sys_id" />
				
            </OutputColumns>
        </EndPoint>
		
		<EndPoint Name="TmpDynamicTableDisaplayValueOutputColumns">
			<OutputColumns>
				<Column Name="[$parent.Pivot_Name$].display_value"
						Label="[$parent.Pivot_Name$]_diaplay_value"
						DataType="DT_WSTR" Length="2000" Expand="True"
						DataEndPoint="get_table_columns"
						DataEndPointParameters="TableName=[$TableName$];"
						DataEndPointWhere="Pivot_Value_internal_type IN ('domain_id','document_id','reference','currency2')"
						ColumnInfoMap="Length=Pivot_Value_max_length;DataType=Pivot_Value_internal_type|ntext=Pivot_Value_max_length(equals:4000)"
                 />

			</OutputColumns>
		</EndPoint>		
		<EndPoint Name="TmpAttachmentTableOutputColumns">
			<OutputColumns>
			  <!-- Primary identifiers -->
			  <Column Name="sys_id"              Label="sys_id"              DataType="DT_WSTR" Length="32" />
			  <Column Name="table_sys_id"        Label="table_sys_id"        DataType="DT_WSTR" Length="32" />

			  <!-- File info -->
			  <Column Name="file_name"           Label="file_name"           DataType="DT_WSTR" Length="512" />
			  <Column Name="content_type"        Label="content_type"        DataType="DT_WSTR" Length="255" />
			  <Column Name="hash"                Label="hash"                DataType="DT_WSTR" Length="64" />
			  <Column Name="state"               Label="state"               DataType="DT_WSTR" Length="50" />

			  <!-- Sizes (numeric, even if quoted in JSON) -->
			  <Column Name="size_bytes"          Label="size_bytes"          DataType="DT_I8" />
			  <Column Name="size_compressed"     Label="size_compressed"     DataType="DT_I8" />
			  <Column Name="chunk_size_bytes"    Label="chunk_size_bytes"    DataType="DT_I8" />

			  <!-- Image metadata -->
			  <Column Name="image_width"         Label="image_width"         DataType="DT_I4" />
			  <Column Name="image_height"        Label="image_height"        DataType="DT_I4" />
			  <Column Name="average_image_color" Label="average_image_color" DataType="DT_WSTR" Length="16" />

			  <!-- Booleans -->
			  <Column Name="compressed"          Label="compressed"          DataType="DT_BOOL" />

			  <!-- Table metadata -->
			  <Column Name="table_name"          Label="table_name"          DataType="DT_WSTR" Length="80" />

			  <!-- Audit fields -->
			  <Column Name="sys_created_by"      Label="sys_created_by"      DataType="DT_WSTR" Length="128" />
			  <Column Name="sys_updated_by"      Label="sys_updated_by"      DataType="DT_WSTR" Length="128" />
			  <Column Name="sys_tags"             Label="sys_tags"            DataType="DT_WSTR" Length="1024" />

			  <!-- Timestamps -->
			  <Column Name="sys_created_on"      Label="sys_created_on"      DataType="DT_DBTIMESTAMP" />
			  <Column Name="sys_updated_on"      Label="sys_updated_on"      DataType="DT_DBTIMESTAMP" />

			  <!-- Counters -->
			  <Column Name="sys_mod_count"       Label="sys_mod_count"       DataType="DT_I4" />

			</OutputColumns>			
        </EndPoint>
		
		<Param Name="TmpQueryParam" 
					   Label="Query / Order By (Server Side Filter)"
					   Type="Query"
					   Key="sysparm_query"
					   Options="Equals (String)=name=Test;
				Equals (Number)=priority=1;
				Not Equal=state!=closed;
				AND Condition=state=active^priority=1;
				OR Condition=state=active^ORstate=pending;
				IN List=stateINactive,pending,closed;
				NOT IN List=stateNOT INactive,closed;
				Starts With=nameSTARTSWITHTest;
				Ends With=nameENDSWITH001;
				Contains (LIKE)=short_descriptionLIKEerror;
				Does Not Contain=short_descriptionNOT LIKEpassword;
				Greater Than (Number)=priority&gt;2;
				Less Than (Number)=priority&lt;4;
				Between Numbers=priority&gt;=2^priority&lt;=4;
				Is Empty=assigned_toISEMPTY;
				Is Not Empty=assigned_toISNOTEMPTY;
				Created After Date=sys_created_on&gt;=2026-01-01;
				Created Before Date=sys_created_on&lt;=2026-01-31 23:59:59;
				Created Today=sys_created_on&gt;=&lt;&lt;today,FUN_TO_DATETIME&gt;&gt;^sys_created_on&lt;=&lt;&lt;today|~|yyyy-MM-dd 23:59:59,FUN_TO_DATETIME&gt;&gt;;
				Updated Last 2 Days=sys_updated_on&gt;=&lt;&lt;today-2d,FUN_TO_DATETIME&gt;&gt;;
				Multiple Conditions Mixed=state=active^priority&gt;1^short_descriptionLIKEerror;
				Order By Column=ORDERBYname;
				Order By Column Desc=ORDERBYDESCsys_created_on;
				Order By Multiple Columns=ORDERBYpriority^ORDERBYDESCsys_created_on;
				Filter + Order=state=active^ORDERBYsys_updated_on;"
					   Desc="Server-side encoded query for filtering and ordering records. Supports string, numeric, date, NULL checks, AND/OR logic, and ORDER BY clauses."
                       HelpLink="https://docs.servicenow.com/bundle/utah-platform-user-interface/page/use/common-ui-elements/reference/r_OpAvailableFiltersQueries.html" />


		<EndPoint Name="TmpGetTableData" 
                  Method="GET" Filter="$.result"
				  CustomErrorRegexPatterns= "Unexpected character encountered"
				  CustomErrorTexts="The ServiceNow instance could not be reached. This can occur if the instance name is incorrect, the instance was reclaimed, or a developer instance is hibernating. Please log in to the instance home page and try again. Original error: {0}"				  
				  >
            <Params>
                <Param Name="TableName" Required="True" Desc="Table name" OptionsEndPoint="get_tables"
                       OptionsEndPointValueColumn="name" />
                <Param Name="SysId" ReadAs="sys_id" IsKey="True" ValueTemplate="/{$value$}" Desc="Row 'sys_id'" />
                <Param Name="Fields" Type="Query" Key="sysparm_fields" MultiSelect="True" MultiSelectSeparator=","
				       Label="Fields to include in response (Keep blank to get all fields -OR- Enter comma separated list)"
                       OptionsEndPoint="get_table_columns" OptionsEndPointValueColumn="name"
                       OptionsEndPointParameters="TableName=[$TableName$]"
                       Desc="Comma-separated field names you want to return in the response. E.g. sys_id,name,label,sys_name,sys_updated_on. Using this setting reduces the response size and speed up the processing." />
				<Param Name="Query" Template="TmpQueryParam" />

                <Param Name="ContineOn404Error" Hidden="True" Type="Property" Value="True" />
                <Param Name="DateFormatString" Type="Property" Value="yyyy-MM-dd HH:mm:ss" />
            </Params>					
        </EndPoint>
		
    </Template>

    <EndPoints>

	
        <!-- GET TABLES **********************************************************-->
        <EndPoint Name="get_tables_admin" Template="TmpTableOutputColumns, TmpPagination"
                  Label="Get List of Tables - Admin (Use sys_db_object)" Url="[$ApiVersion$]table/sys_db_object"
                  Method="GET" Filter="$.result"
                  Desc="Get a list of tables by quering sys_db_object. To read data from this object make sure user has read permission to this table."
                  HelpLink="https://docs.servicenow.com/bundle/rome-application-development/page/integrate/inbound-rest/concept/c_TableAPI.html"
                  CachedTtl="120"
				  CustomErrorRegexPatterns= "Unexpected character encountered"
				  CustomErrorTexts="The ServiceNow instance could not be reached. This can occur if the instance name is incorrect, the instance was reclaimed, or a developer instance is hibernating. Please log in to the instance home page and try again. Original error: {0}"
				  >
            <Params>
                <Param Name="SysId" ReadAs="sys_id" Key="sys_id" IsKey="True" Type="Query" />
                <Param Name="Query" Template="TmpQueryParam" />
                <Param Name="Fields" Key="sysparm_fields" Type="Query" />
            </Params>
        </EndPoint>

        <!-- GET USER TABLES  **********************************************************-->
        <EndPoint Name="get_user_tables_admin" Template="TmpTableOutputColumns, TmpPagination"
                  Label="Get List of User Tables - Admin (Use sys_db_object)"
                  Url="[$ApiVersion$]table/sys_db_object?sysparm_query=sys_created_by!=system" Method="GET"
                  Filter="$.result" Desc="Get a list of tables not created by 'system' user"
                  HelpLink="https://docs.servicenow.com/bundle/rome-application-development/page/integrate/inbound-rest/concept/c_TableAPI.html"
                  CachedTtl="120"
				  CustomErrorRegexPatterns= "Unexpected character encountered"
				  CustomErrorTexts="The ServiceNow instance could not be reached. This can occur if the instance name is incorrect, the instance was reclaimed, or a developer instance is hibernating. Please log in to the instance home page and try again. Original error: {0}"
				  >
            <Params>
                <Param Name="SysId" ReadAs="sys_id" Key="sys_id" IsKey="True" Type="Query" />
            </Params>
        </EndPoint>

        <!-- GET SYSTEM TABLES  **********************************************************-->
        <EndPoint Name="get_system_tables_admin" Template="TmpTableOutputColumns, TmpPagination"
                  Label="Get List of System Tables - Admin (Use sys_db_object)"
                  Url="[$ApiVersion$]table/sys_db_object?sysparm_query=sys_created_by=system" Method="GET"
                  Filter="$.result" Desc="Get a list of tables created by 'system' user"
                  HelpLink="https://docs.servicenow.com/bundle/rome-application-development/page/integrate/inbound-rest/concept/c_TableAPI.html"
                  CachedTtl="120"
				  CustomErrorRegexPatterns= "Unexpected character encountered"
				  CustomErrorTexts="The ServiceNow instance could not be reached. This can occur if the instance name is incorrect, the instance was reclaimed, or a developer instance is hibernating. Please log in to the instance home page and try again. Original error: {0}"				  
				  >
            <Params>
                <Param Name="SysId" ReadAs="sys_id" Key="sys_id" IsKey="True" Type="Query" />
            </Params>
        </EndPoint>

        <!-- GET METADATA  **********************************************************-->
        <EndPoint Name="get_table_columns_admin" Template="TmpPaginationOffset"
                  Label="Get Table Columns - Admin (Use sys_dictionary)" Url="[$ApiVersion$]table/sys_dictionary"
                  Method="GET"
                  Desc="Get a list of columns by quering sys_dictionary. To read data from this table make sure user has read permission to sys_dictionary table."
                  HelpLink="https://docs.servicenow.com/bundle/utah-application-development/page/administer/data-dictionary-tables/concept/c_SystemDictionary.html"
                  DotAsPath="True" UseRawCache="True" CachedTtl="120"
				  CustomErrorRegexPatterns= "Unexpected character encountered"
				  CustomErrorTexts="The ServiceNow instance could not be reached. This can occur if the instance name is incorrect, the instance was reclaimed, or a developer instance is hibernating. Please log in to the instance home page and try again. Original error: {0}"				  
				  >
            <Params>
                <Param Name="TableName" Key="name" ReadAs="name" Required="True" IsKey="True" Type="Query" />
                <Param Name="Filter" Required="True" Type="Property" Value="$.result" />
            </Params>
            <OutputColumns>
                <Column Name="sys_id" DataType="DT_WSTR" Length="500" />
                <Column Name="name" DataType="DT_WSTR" Length="50" />
                <Column Name="element" DataType="DT_WSTR" Length="100" />
                <Column Name="internal_type.value" Label="internal_type" DataType="DT_WSTR" Length="100" />
                <Column Name="max_length" DataType="DT_WSTR" Length="50" />
                <Column Name="column_label" DataType="DT_WSTR" Length="100" />
                <Column Name="sys_name" DataType="DT_WSTR" Length="100" />
                <Column Name="comments" DataType="DT_WSTR" Length="100" />
                <Column Name="calculation" DataType="DT_WSTR" Length="500" />
                <Column Name="dynamic_ref_qual" DataType="DT_WSTR" Length="100" />
                <Column Name="choice_field" DataType="DT_WSTR" Length="100" />
                <Column Name="function_field" DataType="DT_WSTR" Length="50" />
                <Column Name="sys_updated_on" DataType="DT_WSTR" Length="100" />
                <Column Name="spell_check" DataType="DT_WSTR" Length="50" />
                <Column Name="reference_cascade_rule" DataType="DT_WSTR" Length="100" />
                <Column Name="reference" DataType="DT_WSTR" Length="100" />
                <Column Name="sys_updated_by" DataType="DT_WSTR" Length="50" />
                <Column Name="read_only" DataType="DT_WSTR" Length="50" />
                <Column Name="sys_created_on" DataType="DT_WSTR" Length="100" />
                <Column Name="array_denormalized" DataType="DT_WSTR" Length="50" />
                <Column Name="element_reference" DataType="DT_WSTR" Length="50" />
                <Column Name="reference_key" DataType="DT_WSTR" Length="100" />
                <Column Name="reference_qual_condition" DataType="DT_WSTR" Length="100" />
                <Column Name="xml_view" DataType="DT_WSTR" Length="50" />
                <Column Name="dependent" DataType="DT_WSTR" Length="100" />
                <Column Name="internal_type_link" DataType="DT_WSTR" Length="500" />
                <Column Name="sys_created_by" DataType="DT_WSTR" Length="50" />
                <Column Name="use_dependent_field" DataType="DT_WSTR" Length="50" />
                <Column Name="delete_roles" DataType="DT_WSTR" Length="100" />
                <Column Name="virtual_type" DataType="DT_WSTR" Length="100" />
                <Column Name="active" DataType="DT_WSTR" Length="50" />
                <Column Name="choice_table" DataType="DT_WSTR" Length="100" />
                <Column Name="foreign_database" DataType="DT_WSTR" Length="100" />
                <Column Name="sys_update_name" DataType="DT_WSTR" Length="500" />
                <Column Name="unique" DataType="DT_WSTR" Length="50" />
                <Column Name="dependent_on_field" DataType="DT_WSTR" Length="100" />
                <Column Name="dynamic_creation" DataType="DT_WSTR" Length="50" />
                <Column Name="primary" DataType="DT_WSTR" Length="50" />
                <Column Name="sys_policy" DataType="DT_WSTR" Length="100" />
                <Column Name="next_element" DataType="DT_WSTR" Length="100" />
                <Column Name="virtual" DataType="DT_WSTR" Length="50" />
                <Column Name="widget" DataType="DT_WSTR" Length="100" />
                <Column Name="use_dynamic_default" DataType="DT_WSTR" Length="50" />
                <Column Name="sizeclass" DataType="DT_WSTR" Length="100" />
                <Column Name="mandatory" DataType="DT_WSTR" Length="50" />
                <Column Name="sys_class_name" DataType="DT_WSTR" Length="100" />
                <Column Name="dynamic_default_value" DataType="DT_WSTR" Length="100" />

                <Column Name="write_roles" DataType="DT_WSTR" Length="100" />
                <Column Name="array" DataType="DT_WSTR" Length="50" />
                <Column Name="audit" DataType="DT_WSTR" Length="50" />
                <Column Name="read_roles" DataType="DT_WSTR" Length="100" />
                <Column Name="sys_scope_link" DataType="DT_WSTR" Length="500" />
                <Column Name="sys_scope_value" DataType="DT_WSTR" Length="50" />
                <Column Name="create_roles" DataType="DT_WSTR" Length="100" />
                <Column Name="dynamic_creation_script" DataType="DT_WSTR" Length="100" />
                <Column Name="defaultsort" DataType="DT_WSTR" Length="100" />
                <Column Name="use_reference_qualifier" DataType="DT_WSTR" Length="50" />
                <Column Name="display" DataType="DT_WSTR" Length="50" />
                <Column Name="reference_floats" DataType="DT_WSTR" Length="50" />
                <Column Name="sys_mod_count" DataType="DT_WSTR" Length="50" />
                <Column Name="default_value" DataType="DT_WSTR" Length="100" />
                <Column Name="staged" DataType="DT_WSTR" Length="50" />
                <Column Name="reference_type" DataType="DT_WSTR" Length="100" />
                <Column Name="sys_package_link" DataType="DT_WSTR" Length="500" />
                <Column Name="sys_package_value" DataType="DT_WSTR" Length="50" />
                <Column Name="formula" DataType="DT_WSTR" Length="100" />
                <Column Name="attributes" DataType="DT_WSTR" Length="100" />
                <Column Name="choice" DataType="DT_WSTR" Length="100" />
                <Column Name="reference_qual" DataType="DT_WSTR" Length="100" />
                <Column Name="table_reference" DataType="DT_WSTR" Length="50" />
                <Column Name="text_index" DataType="DT_WSTR" Length="50" />
                <Column Name="function_definition" DataType="DT_WSTR" Length="100" />
                <Column Name="sys_scope" DataType="DT_WSTR" Length="100" />
                <Column Name="sys_package" DataType="DT_WSTR" Length="100" />
            </OutputColumns>
        </EndPoint>

        <!-- GET TABLES **********************************************************-->
        <EndPoint Name="get_tables" Label="Get List of Tables" Url="/doc/table/schema" Method="GET" Filter="$.result"
                  Desc="Get a list of tables."
                  HelpLink="https://docs.servicenow.com/bundle/rome-application-development/page/integrate/inbound-rest/concept/c_TableAPI.html"
                  CachedTtl="120"
				  CustomErrorRegexPatterns= "Unexpected character encountered"
				  CustomErrorTexts="The ServiceNow instance could not be reached. This can occur if the instance name is incorrect, the instance was reclaimed, or a developer instance is hibernating. Please log in to the instance home page and try again. Original error: {0}"				  
				  >
            <OutputColumns>
                <Column Name="value" Label="name" DataType="DT_WSTR" Length="500" />
                <Column Name="label" DataType="DT_WSTR" Length="500" />
				<Column Name="raw_label" DataType="DT_WSTR" Length="500" />
				<Column Name="image" DataType="DT_WSTR" Length="500" />
				<Column Name="missing" DataType="DT_BOOL" />
				<Column Name="reference" DataType="DT_BOOL" />
				<Column Name="used" DataType="DT_BOOL" />
				<Column Name="selected" DataType="DT_BOOL" />
            </OutputColumns>
        </EndPoint>

        <!-- GET METADATA  **********************************************************-->
        <EndPoint Name="get_table_columns" Label="Get Table Columns" Url="/ui/meta/[$TableName$]" Method="GET"
                  Desc="Get a list of columns of a table"
                  HelpLink="https://docs.servicenow.com/bundle/utah-application-development/page/administer/data-dictionary-tables/concept/c_SystemDictionary.html"
                  CachedTtl="120">
            <Params>
                <Param Name="TableName" Required="True" Desc="Table name" OptionsEndPoint="get_tables"
                       OptionsEndPointValueColumn="name" />
                <Param Name="Filter" Required="True" Type="Property" Value="$.result.columns" />
                <Param Name="EnablePivot" Type="Property" Value="True" Hidden="True" />
                <Param Name="ElementScopeSeparator" Type="Property" Value="_" Hidden="True" />
				<Param Name="DateTimeValueHandling" Label="Date Time Value Handling" Hidden="False" Type="Property" />
            </Params>

            <OutputColumns>
                <Column Name="Pivot_Value_name" Label="name" DataType="DT_WSTR" Length="128" />
                <Column Name="Pivot_Name" Label="element" DataType="DT_WSTR" Length="128" />
                <Column Name="Pivot_Value_label" Label="label" DataType="DT_WSTR" Length="96" />
                <Column Name="Pivot_Value_internal_type" Label="internal_type" DataType="DT_WSTR" Length="128" />
                <Column Name="Pivot_Value_max_length" Label="max_length" DataType="DT_I8" />
                <Column Name="Pivot_Value_column_type" Label="column_type" DataType="DT_WSTR" Length="128" />
                <Column Name="Pivot_Value_type" Label="type" DataType="DT_WSTR" Length="60" />
                <Column Name="Pivot_Value_filterable" Label="filterable" DataType="DT_BOOL" />
                <Column Name="Pivot_Value_reference_display_field" Label="reference_display_field" DataType="DT_WSTR"
                        Length="60" />
                <Column Name="Pivot_Value_reference_attributes_display_field"
                        Label="reference_attributes_display_field" DataType="DT_WSTR" Length="60" />
                <Column Name="Pivot_Value_reference_attributes_ref_ac_columns"
                        Label="reference_attributes_ref_ac_columns" DataType="DT_WSTR" Length="108" />
                <Column Name="Pivot_Value_reference_attributes_ref_ac_columns_search"
                        Label="reference_attributes_ref_ac_columns_search" DataType="DT_WSTR" Length="80" />
                <Column Name="Pivot_Value_reference_attributes_ref_ac_display_value"
                        Label="reference_attributes_ref_ac_display_value" DataType="DT_BOOL" />
                <Column Name="Pivot_Value_reference_attributes_ref_auto_completer"
                        Label="reference_attributes_ref_auto_completer" DataType="DT_WSTR" Length="80" />
                <Column Name="Pivot_Value_canmatch" Label="canmatch" DataType="DT_BOOL" />
                <Column Name="Pivot_Value_cangroup" Label="cangroup" DataType="DT_BOOL" />
                <Column Name="Pivot_Value_max_unit" Label="max_unit" DataType="DT_WSTR" Length="80" />
                <Column Name="Pivot_Value_mandatory" Label="mandatory" DataType="DT_BOOL" />
                <Column Name="Pivot_Value_reference" Label="reference" DataType="DT_WSTR" Length="100" />
                <Column Name="Pivot_Value_default" Label="default" DataType="DT_WSTR" Length="255" />
                <Column Name="Pivot_Value_base_type" Label="base_type" DataType="DT_WSTR" Length="32" />
                <Column Name="Pivot_Value_read_only" Label="read_only" DataType="DT_BOOL" />
                <Column Name="Pivot_Value_hint" Label="hint" DataType="DT_WSTR" Length="388" />
                <Column Name="Pivot_Value_attributes" Label="attributes" DataType="DT_WSTR" Length="4000" />
                <Column Name="Pivot_Value_cansort" Label="cansort" DataType="DT_BOOL" />
                <Column Name="Pivot_Value_multitext" Label="multitext" DataType="DT_BOOL" />
                <Column Name="Pivot_Value_choice_type" Label="choice_type" DataType="DT_I8" />
                <Column Name="Pivot_Value_choices" Label="choices" DataType="DT_NTEXT" />
            </OutputColumns>

        </EndPoint>
		<EndPoint Name="test_connection"
				  Label="Test Connection"
				  Url="[$ApiVersion$]/table/sys_user?sysparm_limit=1"
				  Method="GET"
				  CustomErrorRegexPatterns= "Unexpected character encountered"
				  CustomErrorTexts="The ServiceNow instance could not be reached. This can occur if the instance name is incorrect, the instance was reclaimed, or a developer instance is hibernating. Please log in to the instance home page and try again. Original error: {0}"
				  >
			<OutputColumns>
				<Column Name="id" Label="Status" ValueTemplate="OK"/>
			</OutputColumns>	
		</EndPoint>
		
		
        <!-- GET TABLE DATA  **********************************************************-->
        <EndPoint Name="get_table_rows" Template="TmpDynamicTableOutputColumns, TmpPagination, TmpGetTableData" Label="Get Table Rows"
                  Url="[$ApiVersion$]table/[$TableName$][$SysId$]" Method="GET" Filter="$.result" Desc="Get table rows"
                  HelpLink="https://www.servicenow.com/docs/r/yokohama/api-reference/rest-apis/c_TableAPI.html"
				  CustomErrorRegexPatterns= "Unexpected character encountered"
				  CustomErrorTexts="The ServiceNow instance could not be reached. This can occur if the instance name is incorrect, the instance was reclaimed, or a developer instance is hibernating. Please log in to the instance home page and try again. Original error: {0}"				  
				  >
            <Params>
            </Params>
        </EndPoint>
		
        <EndPoint Name="get_table_row_count" Label="Get Table Row Count"  
				  Url="stats/[$TableName$]?sysparm_count=true" Method="GET" 
				  Filter="$.result.stats" Desc="Get table row count (count for all rows or for specified query filter)"
                  HelpLink="https://www.servicenow.com/docs/r/yokohama/api-reference/rest-apis/c_TableAPI.html"
				  CustomErrorRegexPatterns= "Unexpected character encountered"
				  CustomErrorTexts="The ServiceNow instance could not be reached. This can occur if the instance name is incorrect, the instance was reclaimed, or a developer instance is hibernating. Please log in to the instance home page and try again. Original error: {0}"				  
				  >
            <Params>
                <Param Name="TableName" Required="True" Desc="Table name" OptionsEndPoint="get_tables" OptionsEndPointValueColumn="name" />
				<Param Name="Query" Template="TmpQueryParam" />
            </Params>
			<OutputColumns>
				<Column Name="count" DataType="DT_I8"/>
			</OutputColumns>
        </EndPoint>

		<EndPoint Name="get_record_labels"
				  Template="TmpDynamicTableOutputColumns,TmpDynamicTableDisaplayValueOutputColumns"
				  Label="Get Record Labels (Tags)"
				  Filter="$.result"
				  Url="[$ApiVersion$]table/label_entry?sysparm_display_value=true&amp;sysparm_query=sys_idISNOTEMPTY[$ParentTableName$][$ParentSysId$][$Query$]"
				  Desc="Returns UI labels (tags) applied to a specific record using the ServiceNow label framework.">
			<Params>
				<Param Name="TableName" Label="Table (***DO NOT CHANGE***)" Value="label_entry" Hidden="True" ValueTemplate="label_entry" />
				<Param Name="ShowDisplayValue" Value="true" Hidden="True" ValueTemplate="true"/>
				<Param Name="ParentTableName"
					   Label="Parent Table Name"
					   OptionsEndPoint="get_tables" OptionsEndPointValueColumn="name"
					   Required="true"
					   Desc="Name of the parent table (for example: incident, problem, change_request)."
					   ValueTemplate="^table={$value$}" />

				<Param Name="ParentSysId"
					   Label="Parent Record Sys_ID"
					   Desc="Sys_ID of the parent record for which labels (tags) should be retrieved."
					   ValueTemplate="^table_key={$value$}" />

				<Param Name="Query"
					   Label="Additional Filter (Optional)"
					   Type="Placeholder"
					   Desc="Optional encoded query to further filter label entries (for example by date or creator)."
					   ValueTemplate="^&lt;&lt;{$value$},FUN_URLENCDATA&gt;&gt;" 
					   Options="
                        Equals (Label Name)=label.name=trial;
                        Starts With (Label)=label.nameSTARTSWITHodbc;
                        Contains (Label)=label.nameLIKEpower;
                        Does Not Contain (Label)=label.nameNOT LIKEdeprecated;
                        Created By User=sys_created_by=admin;
                        Created After Date=sys_created_on&gt;=2026-01-01;
                        Created Before Date=sys_created_on&lt;=2026-01-31 23:59:59;
                        Created Today=sys_created_on&gt;=&lt;&lt;today,FUN_TO_DATETIME&gt;&gt;^sys_created_on&lt;=&lt;&lt;today|~|yyyy-MM-dd 23:59:59,FUN_TO_DATETIME&gt;&gt;;
                        Created Last 7 Days=sys_created_on&gt;=&lt;&lt;today-7d,FUN_TO_DATETIME&gt;&gt;;
                        Multiple Label Filters=label.nameLIKEodbc^label.nameNOT LIKEdeprecated;
                        Order By Label Name=ORDERBYlabel.name;
                        Order By Created Date=ORDERBYsys_created_on;
                        Order By Created Date (Descending)=ORDERBYDESCsys_created_on;
                        Filter + Order=label.nameLIKEtrial^ORDERBYDESCsys_created_on;"
					   
					   />

			</Params>
		</EndPoint>
		
		<!-- GET TABLE ATTACHMENT DATA  **********************************************************-->
        <EndPoint Name="get_attachments" Template="TmpPagination, TmpGetTableData, TmpAttachmentTableOutputColumns" Label="Get Attachments"
                  Url="[$ApiVersion$]table/sys_attachment[$SysId$]?sysparm_query=table_name=[$TableName$][$ParentSysId$][$Query$]" Desc="Get attachment details for a specified table or table + parent sys_id (e.g. incident) or a specific attachment sys_id. You can also search using search criterial related to attachment record (e.g. filename starts with xyz)"
                  HelpLink="https://docs.servicenow.com/bundle/utah-api-reference/page/integrate/inbound-rest/concept/c_AttachmentAPI.html"
				  >

            <Params>
                <Param Name="TableName" Label="TableName (for attachments)" OptionsEndPoint="get_tables"
                       OptionsEndPointValueColumn="name" RequiredIf="SysId==" Desc="Table name for which you like to list attachment. If you supply sys_id of attachment then no need to supply this"  />

                <Param Name="ParentSysId" Desc="Parent Table Row 'sys_id' for which you like to get attachments" ValueTemplate="^table_sys_id={$value$}" />			 
                
                <Param Name="Fields" Type="Query" Key="sysparm_fields" MultiSelect="True" MultiSelectSeparator=","
				       Label="Fields to include in response (Keep blank to get all fields -OR- Enter comma separated list)"
                       OptionsEndPoint="get_table_columns" OptionsEndPointValueColumn="name"
                       OptionsEndPointParameters="TableName=sys_attachment"
                       Desc="Comma-separated field names you want to return in the response. E.g. sys_id,name,label,sys_name,sys_updated_on. Using this setting reduces the response size and speed up the processing." />
				<Param Name="Query" Template="TmpAttachmentQuery" />


            </Params>						
        </EndPoint>

		<EndPoint Name="download_attachment"
				  Label="Download Table Attachment (Single - Using Id)" Url="attachment/[$SysId$]/file"
				  OutputHeaders="StatusCode,x-attachment-metadata">
			<Params>
				<Param Name="SysId"  Label="SysId (i.e. Attachment Id)" IsKey="True" Desc="Attachment Id (i.e. 'sys_id') you like to download"  Required="True" />
				<Param Name="SaveContentAsBinary" Type="Property" Value="True"/>
				<Param Name="TreatResponseAsMultiPart" Type="Property" Value="True" Hidden="True" Desc="ServiceNow returns files wrapped in multipart/form-data but Content-Type header shows file type (e.g., image/png), not multipart. Force multipart parsing to extract file content."/>
				<Param Name="ContinueOn404Error" Key="ContineOn404Error" Type="Property" Value="True" />
				<Param Name="EnableRawOutputModeSingleRow" Type="Property" Value="True" />
				<Param Name="RawOutputDataRowTemplate" Type="Property" Value='{"Status":"Done"}' />
				<Param Name="FileOverwriteMode"
					   Type="Property"
					   Value="AlwaysOverwrite"
					   Required="True"/>
				<Param Key="ResponseDataFile"
					   Name="TargetFilePath"
					   Label="Target File Path (e.g. c:\somefolder\file.xlsx)"
					   Desc="Specify a disk file path to save file as"
					   Required="True"
					   Type="Property"
					   Value=""
					   Editor="FileSave"/>
			</Params>
			<OutputColumns>
				<Column Name="ResponseHeaders_StatusCode" Label="http_status" DataType="DT_I4" />
				<Column Name="ResponseHeaders_x-attachment-metadata" Label="sys_id" DataType="DT_STR" Length="32" ValueTemplate="&lt;&lt;{$value$}|~|$.sys_id,FUN_JSON_TO_TEXT&gt;&gt;"/>
				<Column Name="ResponseHeaders_x-attachment-metadata" Label="size_bytes" DataType="DT_I4" ValueTemplate="&lt;&lt;{$value$}|~|$.size_bytes,FUN_JSON_TO_TEXT&gt;&gt;"/>
				<Column Name="ResponseHeaders_x-attachment-metadata" Label="file_name" DataType="DT_WSTR" ValueTemplate="&lt;&lt;{$value$}|~|$.file_name,FUN_JSON_TO_TEXT&gt;&gt;"/>
				<Column Name="ResponseHeaders_x-attachment-metadata" Label="table_sys_id" DataType="DT_STR" Length="32" ValueTemplate="&lt;&lt;{$value$}|~|$.table_sys_id,FUN_JSON_TO_TEXT&gt;&gt;"/>
				<Column Name="ResponseHeaders_x-attachment-metadata" Label="content_type" DataType="DT_WSTR" ValueTemplate="&lt;&lt;{$value$}|~|$.content_type,FUN_JSON_TO_TEXT&gt;&gt;"/>
			</OutputColumns>
		</EndPoint>		

        <EndPoint Name="download_attachments" Template="TmpPagination, TmpGetTableData" Label="Download Table Attachments (Multiple - Using Query)"
                  Url="[$ApiVersion$]table/sys_attachment[$SysId$]?sysparm_query=table_name=[$TableName$][$ParentSysId$][$Query$]" Desc="Download all attachments for a specified table, or table and its row sys_id or specific attachment sys_id. When files are saved they are given a unique name using the pattern {table_sys_id}_{attachment_sys_id}_{attachment-file_name} so files with the same filename from different parent records will not overwrite each other in the download folder."
                  HelpLink="https://docs.servicenow.com/bundle/utah-api-reference/page/integrate/inbound-rest/concept/c_AttachmentAPI.html"
				  OutputHeaders="StatusCode"
				  >

            <Params>
                <Param Name="OutputMode" Label="Output Mode" Value="True" Options=";SaveToDisk;SaveToDisk" />
                <Param Name="TableName" Label="TableName (for attachments)" OptionsEndPoint="get_tables"
                       OptionsEndPointValueColumn="name" RequiredIf="SysId==" Desc="Table name for which you like to list attachment. If you supply sys_id of attachment then no need to supply this"  />

                <Param Name="ParentSysId" Desc="Parent Table Row 'sys_id' for which you like to get attachments" ValueTemplate="^table_sys_id={$value$}" />			 
                
                <Param Name="Fields" Type="Query" Key="sysparm_fields" MultiSelect="True" MultiSelectSeparator=","
				       Label="Fields to include in response (Keep blank to get all fields -OR- Enter comma separated list)"
                       OptionsEndPoint="get_table_columns" OptionsEndPointValueColumn="name"
                       OptionsEndPointParameters="TableName=sys_attachment"
                       Desc="Comma-separated field names you want to return in the response. E.g. sys_id,name,label,sys_name,sys_updated_on. Using this setting reduces the response size and speed up the processing." />
				<Param Name="Query" Template="TmpAttachmentQuery" />


				<Param Name="OverwriteFile" Value="True" Options=";True;False"/>		
				<Param Name="SaveFolder" Value="" Desc="Specify a disk folder path to save file(s) to (e.g. c:\temp)" Required="True" Editor="FolderOpen"/>	
				<Param Name="ContinueOn404Error" Key="ContineOn404Error" Type="Property" Value="True" />
            </Params>
			<EndPoint Name="child_download_file" Url="attachment/[$parent.sys_id$]/file">
				<Params>	 
					<Param Name="SaveContentAsBinary" Type="Property" Value="True"/>
					<Param Name="TreatResponseAsMultiPart" Type="Property" Value="True" Hidden="True" Desc="ServiceNow returns files wrapped in multipart/form-data but Content-Type header shows file type (e.g., image/png), not multipart. Force multipart parsing to extract file content."/>
					<Param Name="FileOverwriteMode" Type="Property"  />
					<Param Name="ContinueOn404Error" Key="ContineOn404Error" Type="Property" Value="True" />
				</Params>			
			</EndPoint>
		  <OutputColumns>
			<Column Order="-100" Name="p1_table_sys_id" Label="table_sys_id" DataType="DT_STR" Length="32" Desc="Parent Row Id (e.g. Incident, Problem)"/>
			<Column Order="-100" Name="p1_sys_id" Label="sys_id" DataType="DT_STR" Length="32" Desc="Attachment Id" />
			<Column Order="-100" Name="p1_table_name" Label="table_name" DataType="DT_STR" Length="255" />
			<Column Order="-100" Name="p1_file_name" Label="file_name" DataType="DT_WSTR" Length="255" />
			<Column Order="-100" Name="p1_size_bytes" Label="size_bytes" DataType="DT_I8" Desc="File size in bytes from sys_attachment table" />
			<Column Order="-100" Name="p1_content_type" Label="content_type" DataType="DT_WSTR" Length="255" Desc="MIME type of the file (e.g. image/png, application/pdf) from sys_attachment table" />
			<Column Order="-100" Name="p1_hash" Label="hash" DataType="DT_WSTR" Length="64" Desc="File hash for integrity verification from sys_attachment table" />
			<Column Order="-100" Name="p1_sys_created_on" Label="sys_created_on" DataType="DT_DBTIMESTAMP" Desc="When the attachment was created from sys_attachment table" />
			<Column Order="-100" Name="p1_sys_created_by" Label="sys_created_by" DataType="DT_WSTR" Length="128" Desc="User who created the attachment from sys_attachment table" />
			
			<Column Order="-90" Name="data" Label="saved_file_size" DataType="DT_I8" 
			  ValueTemplate="&lt;&lt;[$SaveFolder$]\[$parent.p1_table_sys_id$]_[$parent.p1_sys_id$]_[$parent.p1_file_name$]|~|{$value$}|~|[$OverwriteFile$],FUN_FILE_WRITE_BINARY_SAFE&gt;&gt;" 
			  />
            <Column Name="data" Label="data_bytes" DataType="DT_IMAGE" />
			<Column Order="-80" Name="p1_ResponseHeaders_StatusCode" Label="status_code" DataType="DT_I4" />
			<Column Order="-70" Name="p1_ResponseHeaders_StatusCode" Label="error_message" DataType="DT_STR" ValueTemplate="&lt;&lt;{$value$}|~|EQ:200|~||~|EQ:404|~|Not found|~|Unknown error,FUN_CASE&gt;&gt;" />
			<Column Order="-50" Name="p1_ResponseHeaders_StatusCode" Label="save_folder"  DataType="DT_WSTR" Length="255" ValueTemplate="[$SaveFolder$]" />		
		  </OutputColumns> 
        </EndPoint>	
		
        <EndPoint Name="download_attachments_by_parent_search" Template="TmpPagination, TmpGetTableData" Label="Download Table Attachments By Parent Row Search"
                  Url="[$ApiVersion$]table/[$TableName$][$SysId$]" Method="GET" Filter="$.result" Desc="Download attachments for parent rows returned by the parent query. When files are saved they are given a unique name using the pattern {table_sys_id}_{attachment_sys_id}_{attachment-file_name} so files with the same filename from different parent records will not overwrite each other in the download folder."
                  HelpLink="https://docs.servicenow.com/bundle/utah-api-reference/page/integrate/inbound-rest/concept/c_AttachmentAPI.html"
				  CustomErrorRegexPatterns= "Unexpected character encountered"
				  CustomErrorTexts="The ServiceNow instance could not be reached. This can occur if the instance name is incorrect, the instance was reclaimed, or a developer instance is hibernating. Please log in to the instance home page and try again. Original error: {0}"				  
				  >
			<Params>
				<Param Name="OverwriteFile" Value="True" Options=";True;False"/>		
				<Param Name="SaveFolder" Value="" Desc="Specify a disk folder path to save file(s) to (e.g. c:\temp)" Required="True" Editor="FolderOpen"/>	
				<Param Name="ContinueOn404Error" Key="ContineOn404Error" Type="Property" Value="True" />			
				
				<Param Name="AttachmentQuery" Template="TmpAttachmentQuery" />			
			</Params>
			<EndPoint Name="child_search_attachments" Template="TmpPagination" 
			  Url="[$ApiVersion$]table/sys_attachment?sysparm_query=table_name=[$TableName$]^table_sys_id=[$parent.sys_id$][$AttachmentQuery$]"
			  OutputHeaders="StatusCode"
			  Filter="$.result"
			  >

				<Params>
					<Param Name="TableName" />
					<Param Name="AttachmentQuery" ValueTemplate="^{$value$}"/>
					<Param Name="ParentSysId" />			 
				</Params>
				<EndPoint Name="child_download_file" Url="attachment/[$parent.sys_id$]/file">
					<Params>	 
						<Param Name="SaveContentAsBinary" Type="Property" Value="True"/>
						<Param Name="TreatResponseAsMultiPart" Type="Property" Value="True" Hidden="True" Desc="ServiceNow returns files wrapped in multipart/form-data but Content-Type header shows file type (e.g., image/png), not multipart. Force multipart parsing to extract file content."/>
						<Param Name="ContinueOn404Error" Key="ContineOn404Error" Type="Property" Value="True" />
					</Params>			
				</EndPoint>
			</EndPoint>			
			<OutputColumns>
				<Column Order="-100" Name="p2_table_sys_id" Label="table_sys_id" DataType="DT_STR" Length="32" Desc="Parent Row Id (e.g. Incident, Problem)"/>
				<Column Order="-100" Name="p2_sys_id" Label="sys_id" DataType="DT_STR" Length="32" Desc="Attachment Id" />
				<Column Order="-100" Name="p2_table_name" Label="table_name" DataType="DT_STR" Length="255" />
				<Column Order="-100" Name="p2_file_name" Label="file_name" DataType="DT_WSTR" Length="255" />
				<Column Order="-100" Name="p2_size_bytes" Label="size_bytes" DataType="DT_I8" Desc="File size in bytes from sys_attachment table" />
				<Column Order="-100" Name="p2_content_type" Label="content_type" DataType="DT_WSTR" Length="255" Desc="MIME type of the file (e.g. image/png, application/pdf) from sys_attachment table" />
				<Column Order="-100" Name="p2_hash" Label="hash" DataType="DT_WSTR" Length="64" Desc="File hash for integrity verification from sys_attachment table" />
				<Column Order="-100" Name="p2_sys_created_on" Label="sys_created_on" DataType="DT_DBTIMESTAMP" Desc="When the attachment was created from sys_attachment table" />
				<Column Order="-100" Name="p2_sys_created_by" Label="sys_created_by" DataType="DT_WSTR" Length="128" Desc="User who created the attachment from sys_attachment table" />

				<Column Order="-90" Name="data" Label="saved_file_size" DataType="DT_I8" 
				  ValueTemplate="&lt;&lt;[$SaveFolder$]\[$parent.p2_table_sys_id$]_[$parent.p2_sys_id$]_[$parent.p2_file_name$]|~|{$value$}|~|[$OverwriteFile$],FUN_FILE_WRITE_BINARY_SAFE&gt;&gt;" 
				  />
                <Column Name="data" Label="data_bytes" DataType="DT_IMAGE" />
				<Column Order="-80" Name="p2_ResponseHeaders_StatusCode" Label="status_code" DataType="DT_I4" />
				<Column Order="-70" Name="p2_ResponseHeaders_StatusCode" Label="error_message" DataType="DT_STR" ValueTemplate="&lt;&lt;{$value$}|~|EQ:200|~||~|EQ:404|~|Not found|~|Unknown error,FUN_CASE&gt;&gt;" />
				<Column Order="-50" Name="p2_ResponseHeaders_StatusCode" Label="save_folder"  DataType="DT_WSTR" Length="255" ValueTemplate="[$SaveFolder$]" />		
			</OutputColumns> 			
        </EndPoint>

		<EndPoint Name="get_attachments_by_parent_search" Template="TmpPagination, TmpGetTableData, TmpAttachmentTableOutputColumns" Label="Get Attachments By Parent Row Search"
                  Url="[$ApiVersion$]table/[$TableName$][$SysId$]" Method="GET" Filter="$.result" Desc="Get table rows"
                  HelpLink="https://docs.servicenow.com/bundle/utah-api-reference/page/integrate/inbound-rest/concept/c_AttachmentAPI.html"
				  CustomErrorRegexPatterns= "Unexpected character encountered"
				  CustomErrorTexts="The ServiceNow instance could not be reached. This can occur if the instance name is incorrect, the instance was reclaimed, or a developer instance is hibernating. Please log in to the instance home page and try again. Original error: {0}"				  
				  >
			<Params>
				<Param Name="AttachmentQuery" Template="TmpAttachmentQuery" />			
			</Params>
			<EndPoint Name="child_search_attachments" Template="TmpPagination" 
			  Url="[$ApiVersion$]table/sys_attachment?sysparm_query=table_name=[$TableName$]^table_sys_id=[$parent.sys_id$][$AttachmentQuery$]"
			  OutputHeaders="StatusCode"
			  Filter="$.result" >
				<Params>
					<Param Name="TableName" />
					<Param Name="AttachmentQuery" ValueTemplate="^{$value$}"/>
					<Param Name="ParentSysId" />			 
				</Params>
			</EndPoint>			
        </EndPoint>
		
        <!-- INSERT TABLE ROW  **********************************************************-->
        <EndPoint Name="insert_table_row" Template="TmpDynamicTableOutputColumns,TmpDynamicTableInputColumns"
                  Label="Delete a Table Row" Url="[$ApiVersion$]table/[$TableName$]" Method="POST"
                  ContentType="application/json" JsonRowFormat="Multicontent" Filter="$.result"
                  Desc="Insert a row into the table."
                  HelpLink="https://docs.servicenow.com/bundle/rome-application-development/page/integrate/inbound-rest/concept/c_TableAPI.html"
                  DotAsPath="True"
				  CustomErrorRegexPatterns= "Unexpected character encountered"
				  CustomErrorTexts="The ServiceNow instance could not be reached. This can occur if the instance name is incorrect, the instance was reclaimed, or a developer instance is hibernating. Please log in to the instance home page and try again. Original error: {0}"				  
				  >
            <Params>
                <Param Name="TableName" Required="True" Desc="Table name" OptionsEndPoint="get_tables"
                       OptionsEndPointValueColumn="name" />
            </Params>
            <Body>
                <![CDATA[{$rows$}]]>
            </Body>
        </EndPoint>

        <!-- UPDATE TABLE ROW  **********************************************************-->
        <EndPoint Name="update_table_row" Template="TmpDynamicTableOutputColumns,TmpDynamicTableInputColumns"
                  Label="Update a Table Row" Url="[$ApiVersion$]table/[$TableName$]/[$SysId$]" Method="PUT"
                  ContentType="application/json" JsonRowFormat="Multicontent" Filter="$.result"
                  Desc="Insert a row into the table."
                  HelpLink="https://docs.servicenow.com/bundle/rome-application-development/page/integrate/inbound-rest/concept/c_TableAPI.html"
                  DotAsPath="True"
				  CustomErrorRegexPatterns= "Unexpected character encountered"
				  CustomErrorTexts="The ServiceNow instance could not be reached. This can occur if the instance name is incorrect, the instance was reclaimed, or a developer instance is hibernating. Please log in to the instance home page and try again. Original error: {0}"				  
				  >
            <Params>
                <Param Name="TableName" Required="True" Desc="Table name" OptionsEndPoint="get_tables"
                       OptionsEndPointValueColumn="name" />
                <Param Name="SysId" ReadAs="sys_id" IsKey="True" Required="True" Desc="Row 'sys_id'" />
                <Param Name="ContineOn404Error" Hidden="True" Type="Property" Value="True" />
            </Params>
            <InputColumns>
                <Column Name="SysId" Label="sys_id" ReadAs="sys_id" DataType="DT_WSTR" Length="500" MapToParam="True"
                        Key="True" ExcludeFromRowMap="True" />
            </InputColumns>
            <Body>
                <![CDATA[{$rows$}]]>
            </Body>
        </EndPoint>

        <!-- DELETE TABLE ROW  **********************************************************-->
        <EndPoint Name="delete_table_row" Label="Delete table row" Url="[$ApiVersion$]table/[$TableName$]/[$SysId$]"
                  Method="DELETE" OutputHeaders="StatusCode"
                  Desc="Delete the specified row in the table by row 'sys_id'."
                  HelpLink="https://docs.servicenow.com/bundle/rome-application-development/page/integrate/inbound-rest/concept/c_TableAPI.html"
				  CustomErrorRegexPatterns= "Unexpected character encountered"
				  CustomErrorTexts="The ServiceNow instance could not be reached. This can occur if the instance name is incorrect, the instance was reclaimed, or a developer instance is hibernating. Please log in to the instance home page and try again. Original error: {0}"				  
				  >
            <Params>
                <Param Name="TableName" Required="True" Desc="Table name" OptionsEndPoint="get_tables"
                       OptionsEndPointValueColumn="name" />
                <Param Name="SysId" ReadAs="sys_id" Required="True" IsKey="True" Desc="Row 'sys_id'" />
                <Param Name="RawOutputDataRowTemplate" Type="Property" Value="{}"
                       ValueTemplate="{status:'Deleted', sys_id:'[$SysId$]'}" />
                <Param Name="EnableRawOutputModeSingleRow" Type="Property" Value="True" />
                <Param Name="ContineOn404Error" Hidden="True" Type="Property" Value="True" />
            </Params>
            <InputColumns>
                <Column Name="SysId" Label="sys_id" ReadAs="sys_id" DataType="DT_WSTR" Length="500" MapToParam="True"
                        Key="True" />
            </InputColumns>
            <OutputColumns>
                <Column Name="status" DataType="DT_WSTR" Length="64" />
                <Column Name="sys_id" DataType="DT_WSTR" Length="64" />
                <Column Name="ResponseHeaders_StatusCode" Label="http_status" DataType="DT_I4" />
            </OutputColumns>
        </EndPoint>
        
        <EndPoint Name="upload_attachment"
                    Label="Upload Attachment"
                    Url="/attachment/file"
                    Method="POST"
                    Filter="$.result"
                    Template="TmpAttachmentTableOutputColumns"
                    Desc="Upload a file as an attachment to a ServiceNow record. Requires table name and sys_id in headers."
                    HelpLink="https://docs.servicenow.com/bundle/utah-api-reference/page/integrate/inbound-rest/concept/c_AttachmentAPI.html">
            <Params>
                  <Param Name="TableName" Key="table_name" Type="Query" Label="Table Name (e.g. incident)" OptionsEndPoint="get_tables"
                      OptionsEndPointValueColumn="name" Desc="ServiceNow table to attach file to (e.g. incident)" Required="True" />
                  <Param Name="ParentSysId" Key="table_sys_id" Type="Query" Label="Parent Table Row Id (i.e. table_sys_id)" Desc="Sys ID of the record to attach file to (parent row)" Required="True" />
                  <Param Name="FileName" Key="file_name" Type="Query" Label="File Name" Desc="Name of the file to upload (as it will appear in ServiceNow)." Required="True" />
                  <Param Name="SourceFilePath" Required="True" Type="Placeholder" Label="Source File Path (e.g. c:\uploads\file.pdf)" Desc="Specify a disk file path to upload (e.g. C:\MyParentFolder\Subfolder\file.txt)" Example="C:\MyParentFolder\Subfolder\file.txt" Editor="FileOpen" Value="" />
                  <Param Name="IsMultiPart" Required="True" Type="Property" Hidden="True" Desc="Must be set to 'True'" Value="True" />
                  <Param Name="AddMultiPartPostamble" Type="Property" Hidden="True" Desc="Enable CRLF after final boundary for RFC 7578 compliance" Value="True" />
            </Params>
            <Body>
                <![CDATA[file=@[$SourceFilePath$]
]]>
            </Body>
        </EndPoint>

        <EndPoint Name="delete_attachment"
                  Label="Delete Attachment"
                  Url="[$ApiVersion$]table/sys_attachment/[$SysId$]"
                  Method="DELETE"
                  OutputHeaders="StatusCode"
                  Desc="Delete an attachment by its sys_id."
                  HelpLink="https://docs.servicenow.com/bundle/utah-api-reference/page/integrate/inbound-rest/concept/c_AttachmentAPI.html"
                  CustomErrorRegexPatterns="Unexpected character encountered"
                  CustomErrorTexts="The ServiceNow instance could not be reached. This can occur if the instance name is incorrect, the instance was reclaimed, or a developer instance is hibernating. Please log in to the instance home page and try again. Original error: {0}">
            <Params>
                <Param Name="SysId" Label="Attachment Id (i.e. sys_id)" Desc="Sys ID of the attachment to delete" Required="True" />
                <Param Name="RawOutputDataRowTemplate" Type="Property" Value="{}"
                       ValueTemplate="{status:'Deleted', sys_id:'[$SysId$]'}" />
                <Param Name="EnableRawOutputModeSingleRow" Type="Property" Value="True" />
				<Param Name="ContinueOn404Error" Hidden="True" Type="Property" />
            </Params>
            <OutputColumns>
                <Column Name="status" DataType="DT_WSTR" Length="10" ValueTemplate="Deleted" />
				<Column Name="sys_id" DataType="DT_WSTR" Length="32"  />
                <Column Name="ResponseHeaders_StatusCode" Label="http_status" DataType="DT_I4" />
            </OutputColumns>
        </EndPoint>        
    </EndPoints>

    <Tables>
        <Table Name="Tables" SelectEndPoint="get_tables" />

        <Table Name="[$parent.value$]" Expand="True" ExpandContinueOnError="True" Order="-1" SelectEndPoint="get_table_rows"
               LookupEndPoint="get_table_rows" InsertEndPoint="insert_table_row" UpdateEndPoint="update_table_row"
               DeleteEndPoint="delete_table_row" DataEndPoint="get_tables" DataEndPointParameters="Fields=name">
            <Params>
                <Param Name="TableName" Value="[$parent.value$]" Hidden="True" />
            </Params>
        </Table>
    </Tables>


    <Examples>
        <Example Group="ODBC" Slug="read-incidents" Label="Read incidents" Default="True">
            <Desc>
                <![CDATA[<p>Gets a list of incidents from the <code>incident</code> table. You can use this pattern to read from any other table by changing the table name.</p>]]>
            </Desc>
            <Code>
                <![CDATA[SELECT * FROM incident 

--Using Primary Key				
--SELECT * FROM any_table_here WHERE sys_id='109562a3c611227500a7b7ff98cc0dc7' --Primary Key in WHERE clause

--OR-- 

--Use below to query system / hidden tables (faster response - No Table name lookup needed in below)
SELECT * FROM get_table_rows WITH(TableName='incident', Query='number=INC0000001')

--=================================
--Examples: Using Filter Expression
--=================================
-- Incremental Load Pattern: Load only incidents updated in the last 24 hours (see FUN_TO_DATETIME function help for more information, you can use +/- d, m, y, min,h,s along with now, today, yesterday, weekstart, weekend, monthstart, monthend, yearstart, yearend functions)
--SELECT * FROM incident WITH(Query='sys_updated_on>=<<today-1d,FUN_TO_DATETIME>>')

--SELECT * FROM incident WITH(Query='number=INC0000001') --Equal condition
--SELECT * FROM incident WITH(Query='number!=INC0000001') --Not equal condition
--SELECT * FROM incident WITH(Query='numberININC0000001,INC0000002,INC0000003') --IN condition
--SELECT * FROM incident WITH(Query='number=INC0000001^state=7') --AND condition
--SELECT * FROM incident WITH(Query='number=INC0000001^ORnumber=INC0000002') --OR condition
--SELECT * FROM incident WITH(Query='numberLIKE0001') --LIKE condition
--SELECT * FROM incident WITH(Query='numberSTARTSWITHINC00') --StartWith condition
--SELECT * FROM incident WITH(Query='numberENDSWITH0001') --StartWith condition
--SELECT * FROM incident WITH(Query='number=INC0000001^state=7^NQORnumber=INC0000002') --AND / OR MIXED using NQ (NewQuery Operator)  -- (number=INC0000001 and state=7) OR (number=INC0000002)

--more information about filter here https://docs.servicenow.com/bundle/utah-platform-user-interface/page/use/common-ui-elements/reference/r_OpAvailableFiltersQueries.html


-- To read all available tables execute this query:
-- SELECT * FROM Tables

-- Other common tables:
-----------------------
-- SELECT * FROM sys_db_object
-- SELECT * FROM sys_dictionary
-- SELECT * FROM sys_user
-- SELECT * FROM sys_user_has_role
-- SELECT * FROM sys_user_grmember
-- SELECT * FROM task
-- SELECT * FROM task_sla
-- SELECT * FROM incident
-- SELECT * FROM incident_sla
-- SELECT * FROM change_request
-- SELECT * FROM cmdb_ci_computer
-- SELECT * FROM cmdb_ci_outage
-- SELECT * FROM cmdb_ci
-- SELECT * FROM sn_customerservice_case
-- SELECT * FROM kb_knowledge
-- SELECT * FROM kb_use
-- SELECT * FROM sc_req_item
-- SELECT * FROM sc_request
-- SELECT * FROM sc_task

]]>
            </Code>
        </Example>

<Example Group="ODBC" Slug="read-incidents-incrementally-by-updated-date" Label="Read incidents incrementally (by updated date)">
<Desc>
<![CDATA[
<p>Fetch incidents updated after a specific date.
This pattern is recommended for incremental loads and scheduled sync jobs.</p>

<p>Use this approach to avoid full table scans, reduce API calls,
and improve overall performance.</p>

<p>The date filter can be specified using either a static date value
or a dynamic date expression. Dynamic date expressions allow relative
date calculations and are useful for automated jobs.</p>

<p>Examples of dynamic date expressions:</p>
<ul>
	<li><code>yesterday</code> – incidents updated yesterday</li>
	<li><code>today</code> – incidents updated today</li>
	<li><code>today-1d</code> – incidents updated in the last 24 hours</li>
	<li><code>monthstart</code> – incidents updated since the beginning of the month</li>
	<li><code>monthend-1d</code> – incidents updated up to the last day of the previous month</li>
</ul>

]]>
</Desc>

			<Code>
<![CDATA[
-- Incrementally fetch incidents updated after a given date
SELECT *
FROM get_table_rows
WITH(
TableName='incident',

-- Load only incidents updated in the last 24 hours
Query='sys_updated_on>=<<today-1d,FUN_TO_DATETIME>>'

--OR Updated after static date time
--Query='sys_updated_on>=2025-01-01T23:23:59'
--Query='sys_updated_on>=2025-01-01'

--Other examples of placeholder function usage
--Query='sys_updated_on>=<<monthstart-7d,FUN_TO_DATETIME>>'
--Query='sys_updated_on>=<<monthstart-5d+1y,FUN_TO_DATETIME>>'

)
]]>
			</Code>
		</Example>
		
        <Example Group="ODBC" Slug="read-data-from-system-tables" Label="Read data from system tables">
            <Desc>
                <![CDATA[<p>Gets data from system tables (e.g. <code>sys_choice</code>, <code>sys_journal_field</code>). Many tables are not listed in the <code>get_tables</code> endpoint and are hidden from UI selection. Use the <code>get_table_rows</code> endpoint to query them directly.</p>]]>
            </Desc>
            <Code>
                <![CDATA[
SELECT * FROM get_table_rows WITH(TableName='sys_choice', Query='name=incident^element=close_code')
--SELECT * FROM get_table_rows WITH(TableName='sys_journal_field', Query='name=incident^element=close_code')
				]]>
            </Code>
        </Example>		
        <Example Group="ODBC" Slug="read-incident-by-id" Label="Read an incident by ID">
            <Desc>
                <![CDATA[<p>Gets a single incident by its <code>sys_id</code> (primary key).</p>]]>
            </Desc>
            <Code>
                <![CDATA[SELECT * FROM incident
WHERE sys_id = 'SYS_ID_GOES_HERE']]>
            </Code>
        </Example>
		<Example Group="ODBC" Slug="read-incident-by-number" Label="Read an incident by number">
			<Desc>
				<![CDATA[
		<p>Fetch a specific incident using its human-readable <code>number</code> (for example <code>INC0012345</code>).
		This is the most common lookup used in integrations and support workflows.</p>
		<p>The query filters the <code>incident</code> table using <code>sysparm_query</code> semantics.</p>
		]]>
			</Desc>
			<Code>
				<![CDATA[
-- Query a single incident by incident number
SELECT *
FROM get_table_rows
WITH(
  TableName='incident',
  Query='number=INC0012345'
)
				]]>
			</Code>
		</Example>
		
        <Example Group="ODBC" Slug="read-selected-columns" Label="Read selected columns (performance optimization)">
            <Desc>
                <![CDATA[<p>By default, all column values are returned in the result set. You can instruct the ServiceNow API to send only specific columns by setting the <code>Fields</code> parameter in the <code>WITH</code> clause. This significantly speeds up the response.</p>]]>
            </Desc>
            <Code>
                <![CDATA[SELECT number,name FROM incident WITH (Fields='number,name') --Setting Fields parameter will speed up the query]]>
            </Code>
        </Example>
        <Example Group="ODBC" Slug="read-display-value-of-reference-field" Label="Read display value of a reference field">
            <Desc>
                <![CDATA[<p>Gets related record(s) from a reference field. You need to know the referenced table name for that field, then query by <code>sys_id</code> (Primary Key).</p>]]>
            </Desc>
            <Code>
                <![CDATA[--STEP#1 returns incident number and related company (sys_id)
SELECT number,company FROM incident

--STEP#2 find related table for company field
select name,reference from get_table_columns WITH(TableName='incident') order by 1

--STEP#3 query related table with sys_id returned in step#1
select sys_id, name  from core_company where sys_id='31bea3d53790200044e0bfc8bcbe5dec'        
        
        ]]>
            </Code>
        </Example>
		<Example Group="ODBC" Slug="read-table-using-server-side-filter" Label="Read table using server-side filter">
			<Desc>
				<![CDATA[
<h3>Server-side filtering using ServiceNow native query language</h3>

<p>
This example demonstrates how to filter ServiceNow table data using the native
<strong>server-side filter expression</strong> (sysparm_query) via the
<code>WITH(Query='...')</code> clause.
</p>

<p>
<strong>Why this matters:</strong><br/>
Server-side filtering is executed <em>inside ServiceNow</em> before data is returned.
This dramatically improves performance, reduces network traffic, and avoids unnecessary
client-side processing.
</p>

<p>
Using a SQL <code>WHERE</code> clause without <code>WITH(Query=...)</code> forces the
driver to retrieve more data first and then filter locally, which is slower.
Always prefer <strong>server-side filters first</strong>. Use client-side filtering
only when a condition cannot be expressed using ServiceNow query syntax.
</p>

<hr/>

<h4>ServiceNow query operators (mapped to SQL)</h4>

<table border="1" cellpadding="5" cellspacing="0">
<tr><th>Operator</th><th>Meaning</th><th>SQL Equivalent</th></tr>
<tr><td><code>=</code></td><td>Equals</td><td>=</td></tr>
<tr><td><code>!=</code></td><td>Not equals</td><td>&lt;&gt;</td></tr>
<tr><td><code>IN</code></td><td>In list</td><td>IN (...)</td></tr>
<tr><td><code>LIKE</code></td><td>Contains</td><td>LIKE '%x%'</td></tr>
<tr><td><code>STARTSWITH</code></td><td>Starts with</td><td>LIKE 'x%'</td></tr>
<tr><td><code>ENDSWITH</code></td><td>Ends with</td><td>LIKE '%x'</td></tr>
<tr><td><code>^</code></td><td>AND</td><td>AND</td></tr>
<tr><td><code>^OR</code></td><td>OR (same group)</td><td>OR</td></tr>
<tr><td><code>NQ</code></td><td>New Query (OR group)</td><td>OR (grouped)</td></tr>
</table>

<p>
<strong>Important:</strong><br/>
<ul>
<li><code>^</code> always means <strong>AND</strong></li>
<li><code>^OR</code> applies OR within the same query group</li>
<li><code>NQ</code> starts a <strong>new OR group</strong> (similar to adding parentheses in SQL)</li>
</ul>
</p>

<p>
Example:
<pre>
priority=1^state=2^NQpriority=2^state=3
</pre>

Is equivalent to SQL:
<pre>
(priority = 1 AND state = 2) OR (priority = 2 AND state = 3)
</pre>
</p>

<hr/>

<h4>Date and time filtering using ZappySys Placeholder Engine</h4>

<p>
You can dynamically generate date values using placeholders. These are evaluated
at runtime before the query is sent to ServiceNow.
</p>

<ul>
<li><code>&lt;&lt;today,FUN_TO_DATE&gt;&gt;</code> – today</li>
<li><code>&lt;&lt;yesterday,FUN_TO_DATE&gt;&gt;</code> – yesterday</li>
<li><code>&lt;&lt;today-1d,FUN_TO_DATE&gt;&gt;</code> – today minus 1 day</li>
<li><code>&lt;&lt;today-1m,FUN_TO_DATE&gt;&gt;</code> – today minus 1 month</li>
<li><code>&lt;&lt;monthstart,FUN_TO_DATE&gt;&gt;</code> – current month start</li>
<li><code>&lt;&lt;monthend,FUN_TO_DATE&gt;&gt;</code> – current month end</li>
<li><code>&lt;&lt;yearstart,FUN_TO_DATE&gt;&gt;</code> – year start</li>
<li><code>&lt;&lt;yearend,FUN_TO_DATE&gt;&gt;</code> – year end</li>
</ul>

<p>
See full placeholder documentation here:<br/>
<a href="https://zappysys.com/onlinehelp/odbc-powerpack/scr/odbc-format-static-placeholders.htm#fun_FUN_TO_DATETIME" target="_blank">
ZappySys Placeholder Engine – FUN_TO_DATETIME
</a>
</p>

<hr/>

<h4>Reference documentation</h4>
<ul>
<li><a href="https://www.servicenow.com/docs/r/api-reference/rest-apis/c_TableAPI.html" target="_blank">ServiceNow Table API</a></li>
<li><a href="https://docs.servicenow.com/bundle/utah-platform-user-interface/page/use/common-ui-elements/reference/r_OpAvailableFiltersQueries.html" target="_blank">ServiceNow Filter Operators</a></li>
<li><a href="https://developer.servicenow.com/dev.do#!/learn/learning-plans/xanadu/servicenow_application_developer/app_store_learnv2_rest_xanadu_request_parameters" target="_blank">Advanced Query Parameters</a></li>
</ul>
        ]]>
			</Desc>

			<Code>
				<![CDATA[
-- Basic server-side filter
SELECT * FROM incident WITH(Query='state=2')

-- Primary key lookup (fastest)
SELECT * FROM incident WHERE sys_id='109562a3c611227500a7b7ff98cc0dc7'

-- Not equal
SELECT * FROM incident WITH(Query='state!=6')

-- IN condition
SELECT * FROM incident WITH(Query='priorityIN1,2,3')

-- AND condition
SELECT * FROM incident WITH(Query='priority=1^state=2')
-- SQL: WHERE priority = 1 AND state = 2

-- OR condition (same group)
SELECT * FROM incident WITH(Query='priority=1^ORstate=2')
-- SQL: WHERE priority = 1 OR state = 2

-- AND / OR mixed using NQ
SELECT * FROM incident WITH(Query='priority=1^state=2^NQpriority=2^state=3')
-- SQL: (priority = 1 AND state = 2) OR (priority = 2 AND state = 3)

-- LIKE / StartsWith / EndsWith
SELECT * FROM incident WITH(Query='short_descriptionLIKEemail')
SELECT * FROM incident WITH(Query='numberSTARTSWITHINC')
SELECT * FROM incident WITH(Query='numberENDSWITH001')

-- Date filter using placeholders (last 1 month)
SELECT * FROM incident WITH(Query='opened_at>=<<today-1m,FUN_TO_DATE>>')

-- From month start
SELECT * FROM incident WITH(Query='opened_at>=<<monthstart,FUN_TO_DATE>>')

-- Between dates
SELECT * FROM incident WITH(Query='opened_at>=<<monthstart,FUN_TO_DATE>>^opened_at<=<<monthend,FUN_TO_DATE>>')
        ]]>
			</Code>
		</Example>


		<Example Group="ODBC" Slug="create-incident" Label="Create an incident">
            <Desc>
                <![CDATA[<p>Creates a new incident record.</p>]]>
            </Desc>
            <Code>
                <![CDATA[INSERT INTO incident(incident_state, severity, category, cause)
VALUES (3, 1, 'software', 'Missing a software feature.')]]>
            </Code>
        </Example>
		<Example Group="ODBC" Slug="create-incident-using-display-values" Label="Create an incident using display values">
			<Desc>
				<![CDATA[
		<p>This example demonstrates how to create a new <code>incident</code> record by supplying
		<strong>human-readable labels (display values)</strong> for reference fields instead of
		their underlying <code>sys_id</code> values.</p>

		<p>Normally, ServiceNow requires reference fields (such as <code>caller_id</code> or
		<code>assignment_group</code>) to be populated using the target record's <code>sys_id</code>.
		In this example, label-to-ID resolution is explicitly enabled using
		<code>AllowDisplayValueAsInput='true'</code>, allowing display values to be passed instead.</p>

		<p>This approach is useful for ad-hoc operations, demos, or interactive usage.
		For automated or high-volume integrations, using <code>sys_id</code> values is strongly recommended.</p>
		]]>
			</Desc>

			<Code>
				<![CDATA[
-- Create a new Incident using DISPLAY VALUES (labels) for reference fields
-- Instead of passing sys_id values, this example uses human-readable labels.
-- This works ONLY because AllowDisplayValueAsInput='true' is specified.

INSERT INTO incident
(
	short_description,
	incident_state,
	severity,
	category,
	caller_id,           -- reference to sys_user
	assignment_group     -- reference to sys_user_group
)
VALUES
(
	'Email service is intermittently failing',
	2,                   -- In Progress
	1,                   -- High severity
	'software',
	'John Doe',          -- LABEL (user display name), not sys_id
	'Network'            -- LABEL (group name), not sys_id
)
WITH(AllowDisplayValueAsInput='true')
				]]>
			</Code>

			<Note>
				<![CDATA[
		If <code>AllowDisplayValueAsInput</code> is not specified or is set to <code>false</code>,
		reference fields must be populated using the record <strong>sys_id</strong>.
		Passing display values (labels) such as user names or group names will fail unless
		label-to-ID resolution is explicitly enabled.
		]]>
			</Note>
		</Example>
		
		
        <Example Group="ODBC" Slug="update-incident" Label="Update an incident">
            <Desc>
                <![CDATA[<p>Updates an existing incident record.</p>]]>
            </Desc>
            <Code>
                <![CDATA[UPDATE incident
SET cause = 'A bug in the software'
   ,severity = 3
   ,incident_state = 2
WHERE sys_id = 'SYS_ID_GOES_HERE']]>
            </Code>
        </Example>
        <Example Group="ODBC" Slug="delete-incident" Label="Delete an incident">
            <Desc>
                <![CDATA[<p>Deletes an incident record.</p>]]>
            </Desc>
            <Code>
                <![CDATA[DELETE FROM incident
WHERE sys_id = 'SYS_ID_GOES_HERE']]>
            </Code>
        </Example>

        <Example Group="ODBC" Slug="read-list-of-tables" Label="Read list of tables">
            <Desc>
                <![CDATA[<p>Gets a list of all available tables.</p>]]>
            </Desc>
            <Code>
                <![CDATA[SELECT * FROM Tables]]>
            </Code>
        </Example>
        <Example Group="ODBC" Slug="read-columns-of-table" Label="Read columns of a table">
            <Desc>
                <![CDATA[<p>Gets column metadata for a specific table.</p>]]>
            </Desc>
            <Code>
                <![CDATA[SELECT * FROM get_table_columns WITH(TableName='TableNameGoesHere')]]>
            </Code>
        </Example>
        <Example Group="ODBC" Slug="read-all-columns-of-all-tables" Label="Read all columns of all tables">
            <Desc>
                <![CDATA[<p>Gets column metadata for all tables. This operation can be slow.</p>]]>
            </Desc>
            <Code>
                <![CDATA[SELECT * FROM get_table_columns_admin WITH(TableName='*') --requires readonly permissions on sys_dictionary and sys_db_object tables]]>
            </Code>
        </Example>
        <Example Group="ODBC" Slug="read-any-api-endpoint-generic-request" Label="Read any API endpoint (generic request)">
            <Desc>
                <![CDATA[<p>Uses the <code>generic_request</code> endpoint to access any ServiceNow API. Use the ServiceNow API Reference and Query Builder to build custom requests.</p>]]>
            </Desc>
            <Code>
                <![CDATA[SELECT *
FROM generic_request
WITH(
	Url='/v2/table/incident?sysparm_limit=10000&sysparm_query=numberLIKE0001^ORDERBYsys_created_on',
	Filter='$.result',
	Meta='sys_id:string;number:string;business_stc:int', --//comment this to see all columns (SLOW)
	PagingMode='ByResponseHeaderRfc5988'
  --Method='GET',
  --Body='{your POST body}'  
)

-- Request URL should be partial like this one:
-- /v2/some_table?some-parameter=somevalue1&some-parameter=somevalue2
]]>
            </Code>
        </Example>

		<Example Group="ODBC" Slug="read-attachments-information" Label="Read attachments information">
			<Desc>
				<![CDATA[
<p>This example set demonstrates how to use the <code>get_attachments</code> endpoint.  
This endpoint retrieves attachment metadata directly from the ServiceNow <code>sys_attachment</code> table, allowing fast server-side filtering on attachment-level attributes. Use it when you want to query attachments across a table without first filtering parent records. For parent-level filtering (slower per-parent processing), use the <code>Get Attachments By Parent Row Search</code> endpoint instead.</p>

<p>Use the <code>Query</code> parameter for server-side filters on the <code>sys_attachment</code> table (examples: <code>file_nameENDSWITH.png</code>, <code>content_typeSTARTSWITHimage/</code>, <code>size_bytes&gt;1048576</code>, or date placeholders like <code>&lt;&lt;today-2d,FUN_TO_DATETIME&gt;&gt;</code>). You can also specify a <code>ParentSysId</code> to limit to a single parent record or use <code>SysId</code> for a specific attachment. Replace sample sys_id and table names with values from your instance.</p>
]]>
			</Desc>
			<Code>
				<![CDATA[
-- Get all attachments for the parent table 'problem'
SELECT * FROM get_attachments WITH(TableName='problem')

-- Get attachments where file name ends with .png or .zip (attachment table filter)
SELECT * FROM get_attachments WITH(TableName='problem', Query='file_nameENDSWITH.png^ORfile_nameENDSWITH.zip')

-- Get all attachments for a specific parent record (by parent sys_id)
SELECT * FROM get_attachments WITH(TableName='problem', ParentSysId='62304320731823002728660c4cf6a7e8')

-- Get a single attachment metadata row by exact attachment sys_id
SELECT * FROM get_attachments WITH(SysId='4b2d41168396b21032ddb9f6feaad38f')

-- Get attachments uploaded today
SELECT * FROM get_attachments WITH(TableName='problem', Query='sys_created_on>=<<today,FUN_TO_DATETIME>>^sys_created_on<=<<today|~|yyyy-MM-dd 23:59:59,FUN_TO_DATETIME>>')

-- Get attachments uploaded in the last 2 days
SELECT * FROM get_attachments WITH(TableName='problem', Query='sys_created_on>=<<today-2d,FUN_TO_DATETIME>>')

-- Get attachments uploaded after a specific date
SELECT * FROM get_attachments WITH(TableName='problem', Query='sys_created_on>=2026-01-01')

-- Get attachments with exact file name match
SELECT * FROM get_attachments WITH(TableName='problem', Query='file_name=dump.png')

-- Get attachments where file name starts with 'dump'
SELECT * FROM get_attachments WITH(TableName='problem', Query='file_nameSTARTSWITHdump')

-- Get attachments where file name contains 'error'
SELECT * FROM get_attachments WITH(TableName='problem', Query='file_nameLIKEerror')

-- Get attachments where file name ends with .pdf
SELECT * FROM get_attachments WITH(TableName='problem', Query='file_nameENDSWITH.pdf')

-- Get only image attachments
SELECT * FROM get_attachments WITH(TableName='problem', Query='content_typeSTARTSWITHimage/')

-- Get attachments larger than 1 MB
SELECT * FROM get_attachments WITH(TableName='problem', Query='size_bytes>1048576')

-- Get attachments uploaded by a specific user
SELECT * FROM get_attachments WITH(TableName='problem', Query='sys_created_by=admin')

-- Order attachments by created date (ascending)
SELECT * FROM get_attachments WITH(TableName='problem', Query='ORDERBYsys_created_on')

-- Order attachments by size descending
SELECT * FROM get_attachments WITH(TableName='problem', Query='ORDERBYDESCsize_bytes')
                ]]>
			</Code>
		</Example>

		<Example Group="ODBC" Slug="read-attachments-by-parent-record" Label="Read attachments by parent record">
			<Desc>
				<![CDATA[
<p>This example set demonstrates how to use the <code>get_attachments_by_parent_search</code> endpoint.  
This endpoint first finds parent rows (for example, records in the <code>problem</code> table) using a parent-level <code>Query</code>, then for each parent record fetches attachments using the <code>AttachmentQuery</code> filter. Because it performs a per-parent lookup it can be slower than direct attachment-table queries, but it is useful when you must filter by parent record attributes (for example, problems updated in the last 2 days).</p>

<p>Use the <code>AttachmentQuery</code> to apply server-side filters on the <code>sys_attachment</code> table (examples: <code>file_nameENDSWITH.png</code>, <code>content_typeSTARTSWITHimage/</code>, <code>size_bytes&gt;1048576</code>, or date placeholders like <code>&lt;&lt;today-2d,FUN_TO_DATETIME&gt;&gt;</code>). Replace sample sys_id and table names with values from your instance.</p>
]]>
			</Desc>
			<Code>
				<![CDATA[
-- Find attachments for specific parent records (multiple parent IDs)
SELECT * FROM get_attachments_by_parent_search
WITH(TableName='problem', Query='sys_idIN62304320731823002728660c4cf6a7e8,6632130c730123002728660c4cf6a734')

-- Parent-level filter: problems updated in last 2 days; attachment-level filter: file name ends with .png or .zip
SELECT * FROM get_attachments_by_parent_search
WITH(
  TableName='problem',
  Query='sys_updated_on>=<<today-2d,FUN_TO_DATETIME>>',
  AttachmentQuery='file_nameENDSWITH.png^ORfile_nameENDSWITH.zip'
)

-- Parent-level filter by sys_id and attachment filter by exact file name
SELECT * FROM get_attachments_by_parent_search
WITH(TableName='problem', Query='sys_id=62304320731823002728660c4cf6a7e8', AttachmentQuery='file_name=dump.png')

-- Attachments uploaded by a specific user for parents matched by parent query
SELECT * FROM get_attachments_by_parent_search
WITH(TableName='incident', Query='opened_by=jsmith', AttachmentQuery='sys_created_by=jsmith')

-- Attachments larger than 1 MB for problems updated in the last month
SELECT * FROM get_attachments_by_parent_search
WITH(
  TableName='problem',
  Query='sys_updated_on>=<<today-1m,FUN_TO_DATETIME>>',
  AttachmentQuery='size_bytes>1048576'
)

-- Only image attachments (content type starts with "image/") for a given parent
SELECT * FROM get_attachments_by_parent_search
WITH(TableName='problem', Query='sys_id=62304320731823002728660c4cf6a7e8', AttachmentQuery='content_typeSTARTSWITHimage/')

-- Order attachments by creation date (per-parent results ordered by attachment date)
SELECT * FROM get_attachments_by_parent_search
WITH(TableName='problem', Query='sys_updated_on>=<<today-2d,FUN_TO_DATETIME>>', AttachmentQuery='ORDERBYsys_created_on')

-- Combine parent IN-list and attachment name contains filter
SELECT * FROM get_attachments_by_parent_search
WITH(
  TableName='problem',
  Query='sys_idIN62304320731823002728660c4cf6a7e8,6632130c730123002728660c4cf6a734',
  AttachmentQuery='file_nameLIKEerror'
)
                ]]>
			</Code>
		</Example>

		<Example Group="ODBC" Slug="download-attachments" Label="Download attachments">
			<Desc>
				<![CDATA[
<p>This example set demonstrates how to use the <code>download_attachments</code> endpoint.  
This endpoint downloads attachment files directly from the ServiceNow <code>sys_attachment</code> table based on server-side filters. It retrieves and saves files to a specified folder, allowing fast filtering on attachment-level attributes. For parent-level filtering (slower per-parent processing), use the <code>Download Table Attachments By Parent Row Search</code> endpoint instead.</p>

<p>Use the <code>Query</code> parameter for server-side filters on the <code>sys_attachment</code> table (examples: <code>file_nameENDSWITH.png</code>, <code>content_typeSTARTSWITHimage/</code>, <code>size_bytes&gt;1048576</code>, or date placeholders like <code>&lt;&lt;today-2d,FUN_TO_DATETIME&gt;&gt;</code>). Specify <code>SaveFolder</code> for the download directory and <code>OverwriteFile</code> to control file overwriting (True to always overwrite, False to fail if the file exists). You can also specify a <code>ParentSysId</code> to limit to a single parent record or use <code>SysId</code> for a specific attachment. Replace sample sys_id and table names with values from your instance.</p>

<p>Note: downloaded files are saved using a unique filename pattern <code>{table_sys_id}_{attachment_sys_id}_{attachment-file_name}</code>. This prevents overwriting when multiple parent records contain attachments with the same filename and you save them into the same download directory.</p>
]]>
			</Desc>
			<Code>
				<![CDATA[
-- Download all attachments for the parent table 'problem' to c:\temp (always overwrite existing files)
SELECT * FROM download_attachments WITH(TableName='problem', SaveFolder='c:\temp', OverwriteFile='True')

-- Download attachments where file name ends with .png or .zip to c:\temp (fail if file exists)
SELECT * FROM download_attachments WITH(TableName='problem', Query='file_nameENDSWITH.png^ORfile_nameENDSWITH.zip', SaveFolder='c:\temp', OverwriteFile='False')

-- Download all attachments for a specific parent record (by parent sys_id) to c:\temp
SELECT * FROM download_attachments WITH(TableName='problem', ParentSysId='62304320731823002728660c4cf6a7e8', SaveFolder='c:\temp', OverwriteFile='True')

-- Download a single attachment by exact attachment sys_id to c:\temp
SELECT * FROM download_attachments WITH(SysId='4b2d41168396b21032ddb9f6feaad38f', SaveFolder='c:\temp', OverwriteFile='True')

-- Download attachments uploaded in the last 2 days to c:\temp
SELECT * FROM download_attachments WITH(TableName='problem', Query='sys_created_on>=<<today-2d,FUN_TO_DATETIME>>', SaveFolder='c:\temp', OverwriteFile='True')

-- Download only image attachments larger than 1 MB to c:\temp
SELECT * FROM download_attachments WITH(TableName='problem', Query='content_typeSTARTSWITHimage/^size_bytes>1048576', SaveFolder='c:\temp', OverwriteFile='False')
                ]]>
			</Code>
		</Example>

		<Example Group="ODBC" Slug="download-attachments-by-parent-record" Label="Download attachments by parent record">
			<Desc>
				<![CDATA[
<p>This example set demonstrates how to use the <code>download_attachments_by_parent_search</code> endpoint.  
This endpoint first finds parent rows (for example, records in the <code>problem</code> table) using a parent-level <code>Query</code>, then downloads attachments for each matching parent record using the <code>AttachmentQuery</code> filter. Because it performs a per-parent lookup, it can be slower than direct attachment-table downloads, but it is useful when you must filter by parent record attributes (for example, problems updated in the last 2 days).</p>

<p>Use the <code>AttachmentQuery</code> to apply server-side filters on the <code>sys_attachment</code> table (examples: <code>file_nameENDSWITH.png</code>, <code>content_typeSTARTSWITHimage/</code>, <code>size_bytes&gt;1048576</code>, or date placeholders like <code>&lt;&lt;today-2d,FUN_TO_DATETIME&gt;&gt;</code>). Specify <code>SaveFolder</code> for the download directory and <code>OverwriteFile</code> to control file overwriting (True to always overwrite, False to fail if the file exists). Replace sample sys_id and table names with values from your instance.</p>

<p>Note: downloaded files are saved using a unique filename pattern <code>{table_sys_id}_{attachment_sys_id}_{attachment-file_name}</code>. This prevents overwriting when multiple parent records contain attachments with the same filename and you save them into the same download directory.</p>
]]>
			</Desc>
			<Code>
				<![CDATA[
-- Download attachments for specific parent records (multiple parent IDs) to c:\temp (always overwrite)
SELECT * FROM download_attachments_by_parent_search
WITH(TableName='problem', Query='sys_idIN62304320731823002728660c4cf6a7e8,6632130c730123002728660c4cf6a734', SaveFolder='c:\temp', OverwriteFile='True')

-- Parent-level filter: problems updated in last 2 days; attachment-level filter: file name ends with .png or .zip; save to c:\temp (fail if file exists)
SELECT * FROM download_attachments_by_parent_search
WITH(
  TableName='problem',
  Query='sys_updated_on>=<<today-2d,FUN_TO_DATETIME>>',
  AttachmentQuery='file_nameENDSWITH.png^ORfile_nameENDSWITH.zip',
  SaveFolder='c:\temp',
  OverwriteFile='False'
)

-- Parent-level filter by sys_id and attachment filter by exact file name; save to c:\temp
SELECT * FROM download_attachments_by_parent_search
WITH(TableName='problem', Query='sys_id=62304320731823002728660c4cf6a7e8', AttachmentQuery='file_name=dump.png', SaveFolder='c:\temp', OverwriteFile='True')

-- Attachments larger than 1 MB for problems updated in the last month; save to c:\temp
SELECT * FROM download_attachments_by_parent_search
WITH(
  TableName='problem',
  Query='sys_updated_on>=<<today-1m,FUN_TO_DATETIME>>',
  AttachmentQuery='size_bytes>1048576',
  SaveFolder='c:\temp',
  OverwriteFile='True'
)

-- Only image attachments for a given parent; save to c:\temp (fail if file exists)
SELECT * FROM download_attachments_by_parent_search
WITH(TableName='problem', Query='sys_id=62304320731823002728660c4cf6a7e8', AttachmentQuery='content_typeSTARTSWITHimage/', SaveFolder='c:\temp', OverwriteFile='False')
                ]]>
			</Code>
		</Example>

		<Example Group="ODBC" Slug="download-attachment-by-id" Label="Download an attachment by ID">
			<Desc>
				<![CDATA[
<p>This example demonstrates how to use the <code>download_attachment</code> endpoint to download a single attachment file by its exact <code>sys_id</code>. Unlike bulk download endpoints, this allows you to specify a custom <code>TargetFilePath</code> for precise control over the saved file name and location. It does not support filters, as it targets one specific attachment.</p>

<p>Specify the attachment's <code>SysId</code>, the full <code>TargetFilePath</code> (e.g., <code>c:\temp\myfile.png</code>), and <code>FileOverwriteMode</code> to control behavior if the file exists (0 or 'AlwaysOverwrite' to overwrite, 1 or 'FailIfExists' to fail, 2 or 'SkipIfExists' to skip). Replace the sample sys_id with a valid attachment ID from your instance.</p>
]]>
			</Desc>
			<Code>
				<![CDATA[
-- Download a single attachment by sys_id to a custom file path (always overwrite if exists)
SELECT * FROM download_attachment 
WITH(
    SysId='4b2d41168396b21032ddb9f6feaad38f', 
    TargetFilePath='c:\temp\dump_saved.png', 
	
	--Set overwrite mode : 0=AlwaysOverwrite, 1=FailIfExists, 2=SkipIfExists
    FileOverwriteMode=0 
)

-- Download another attachment with a different name (fail if file exists)
SELECT * FROM download_attachment 
WITH(
    SysId='another_attachment_sys_id_here', 
    TargetFilePath='c:\downloads\report.pdf', 
    FileOverwriteMode='FailIfExists'
)

-- Download using numeric value for skip if exists
SELECT * FROM download_attachment 
WITH(
    SysId='third_attachment_sys_id_here', 
    TargetFilePath='c:\files\data.xlsx', 
    FileOverwriteMode=2
)
                ]]>
			</Code>
		</Example>

		<Example Group="ODBC" Slug="upload-attachment" Label="Upload an attachment">
			<Desc>
				<![CDATA[
<p>Upload a file and attach it to a specific record. <strong>ParentSysId</strong> refers to the parent record's <code>sys_id</code> (table_sys_id) where the attachment will be linked. Provide the target <code>TableName</code>, the <code>ParentSysId</code>, the desired <code>FileName</code> as it appears in ServiceNow, and the local <code>SourceFilePath</code>.</p>
]]>
			</Desc>
			<Code>
				<![CDATA[
-- Upload and attach local file to a 'incident' record 
SELECT * FROM upload_attachment 
WITH(
  TableName='incident',
  --below is sys_id from 'incident' table where you like to attach uploaded file
  ParentSysId='62304320731823002728660c4cf6a7e8',
  FileName='dump_saved.png',
  SourceFilePath='c:\temp\dump_saved.png'
)
                ]]>
			</Code>
		</Example>
		
        <Example Group="ODBC" Slug="delete-attachment" Label="Delete an attachment">
            <Desc>
                <![CDATA[
<p>Delete a single attachment by its <code>sys_id</code>. <strong>SysId</strong> is the attachment's id in the <code>sys_attachment</code> table. Provide the <code>TableName</code> (optional for clarity) and the attachment <code>SysId</code>.</p>
]]>
            </Desc>
            <Code>
                <![CDATA[
-- Delete a single attachment by attachment sys_id
SELECT * FROM delete_attachment
WITH(
  TableName='problem', -- optional, used for context
  SysId='d871411783d6321032ddb9f6feaad339'
)
                ]]>
            </Code>
        </Example>	

		<Example Group="ODBC" Slug="read-incident-work-notes" Label="Read incident work notes">
			<Desc>
<![CDATA[
<p>Retrieve <strong>Work Notes</strong> added to incidents. Work notes are stored as journal entries
in the <code>sys_journal_field</code> table, not directly on the incident record.</p>
<p>This example returns all internal notes entered by agents.</p>
]]>
			</Desc>
			<Code>
<![CDATA[
-- Get work notes for all incidents
SELECT *
FROM get_table_rows
WITH(
	TableName='sys_journal_field',
	Query='name=incident^element=work_notes'
)
]]>
			</Code>
		</Example>

		<Example Group="ODBC" Slug="read-incident-additional-comments" Label="Read incident additional comments">
			<Desc>
<![CDATA[
<p>Fetch <strong>Additional Comments</strong> (customer-visible notes) for incidents.
These comments are typically shared with end users and customers.</p>
<p>Data is sourced from the ServiceNow journal table.</p>
]]>
			</Desc>
			<Code>
<![CDATA[
-- Get customer-facing comments for incidents
SELECT *
FROM get_table_rows
WITH(
TableName='sys_journal_field',
Query='name=incident^element=comments'
)
]]>
			</Code>
		</Example>

		<Example Group="ODBC" Slug="read-incident-tasks" Label="Read incident tasks">
			<Desc>
<![CDATA[
<p>Retrieve all tasks associated with a specific incident.
Incident tasks are stored in the <code>incident_task</code> table and linked
using the parent incident reference.</p>

<p>You can use static date or function as above. This function expression can be in the form of [function_name][+/-][interval][interval][+/-][interval]... For example to get Last date of previous month you can do "monthend-1d". To get yesterday's date you can just type "yesterday". Valid date function names for this expression are [ now | today | yesterday | weekstart | weekend | monthstart | monthend | yearstart | yearend ]. 
Valid interval names are [ms (for milliseconds) | s OR sec | min | h OR hour | y OR year | d OR day |m OR month | y OR year] </p>
]]>
			</Desc>
			<Code>
<![CDATA[
-- Get all tasks for a specific incident
SELECT *
FROM get_table_rows
WITH(
    TableName='incident_task',
    Query='incident.number=INC0012345'
)
]]>
			</Code>
		</Example>
		
		<Example Group="ODBC" Slug="read-attachments-for-incident" Label="Read attachments for an incident">
			<Desc>
<![CDATA[
<p>Retrieve all file attachments linked to a specific incident.
Attachments are stored in the <code>sys_attachment</code> table.</p>
<p>This example is commonly used before downloading or deleting attachments.</p>
]]>
			</Desc>
			<Code>
<![CDATA[
-- List attachments linked to an incident
SELECT *
FROM get_table_rows
WITH(
	TableName='sys_attachment',
	Query='table_name=incident^table_sys_id=<<INCIDENT_SYS_ID>>'
)
]]>
			</Code>
		</Example>

		<Example Group="ODBC" Slug="read-dropdown-labels-and-values" Label="Read dropdown labels and values">
			<Desc>
<![CDATA[
<p>Resolve and list <strong>dropdown (choice) field labels and values</strong>
for any ServiceNow table or form screen.</p>

<p>ServiceNow stores dropdown fields as internal values
(for example <code>4</code>) while displaying user-friendly labels
(such as <code>4 - Low</code>) in the UI. These mappings are defined
in the <code>sys_choice</code> system table.</p>

<p>Use this example to discover and resolve dropdown options for fields like
<strong>Priority</strong>, <strong>State</strong>, <strong>Category</strong>,
<strong>Close Code</strong>, and any custom choice field across all ServiceNow tables.</p>
]]>
			</Desc>
			<Code>
				<![CDATA[
-- Resolve and list dropdown (choice) labels and values for any table and field
-- Replace <TABLE_NAME> and <FIELD_NAME> with your target form field (e.g. name=incident^element=priority)

SELECT *
FROM get_table_rows
WITH(
  TableName='sys_choice',
  Query='name=<TABLE_NAME>^element=<FIELD_NAME>'
)
				]]>
			</Code>
		</Example>

		<Example Group="ODBC" Slug="read-incidents-using-reference-fields" Label="Read incidents using reference fields">
			<Desc>
				<![CDATA[
<p>Demonstrates how to query the <code>incident</code> table using
<strong>reference (foreign key) fields</strong> in ServiceNow.</p>

<p>ServiceNow allows filtering on fields from related tables using
<strong>dot-walking</strong> syntax (<code>reference_field.some_field</code>),
without requiring explicit joins.</p>

<p>Use these patterns to filter incidents by <strong>Caller</strong>,
<strong>Assigned User</strong>, <strong>Assignment Group</strong>,
<strong>Configuration Item</strong>, or other referenced records.</p>
]]>
			</Desc>

			<Code>
<![CDATA[
-- 1. Query incidents by caller's username (caller_id → sys_user)
SELECT *
FROM get_table_rows
WITH(
	TableName='incident',
	Query='caller_id.user_name=john.doe'
) 

-- 2. Query incidents by assigned user's display name (assigned_to → sys_user)
SELECT *
FROM get_table_rows
WITH(
	TableName='incident',
	Query='assigned_to.name=Jane Smith'
) 

-- 3. Query incidents by assignment group name (assignment_group → sys_user_group)
SELECT *
FROM get_table_rows
WITH(
	TableName='incident',
	Query='assignment_group.name=Network'
) 

-- 4. Query incidents by configuration item name (cmdb_ci → CMDB record)
SELECT *
FROM get_table_rows
WITH(
	TableName='incident',
	Query='cmdb_ci.name=SRV-APP-01'
) 

-- 5. Combine reference field and local field filters
--    (Network group + High priority incidents)
SELECT *
FROM get_table_rows
WITH(
	TableName='incident',
	Query='assignment_group.name=Network^priority=1'
) 
]]>
			</Code>
		</Example>


		<Example Group="ODBC" Slug="read-record-labels-tags" Label="Read record labels (tags)">
			<Desc>
				<![CDATA[
<p>This example demonstrates how to retrieve and filter <strong>UI labels (tags)</strong>
applied to a specific record in ServiceNow using the
<code>get_record_labels</code> endpoint.</p>

<p>The endpoint queries the <code>label_entry</code> table and scopes results using:</p>
<ul>
	<li><code>ParentTableName</code> – the name of the parent table (for example <code>incident</code> or <code>problem</code>)</li>
	<li><code>ParentSysId</code> – the <code>sys_id</code> of the parent record</li>
</ul>

<p>Additional filtering is applied using the <code>Query</code> parameter.
Filtering must use <strong>real database fields</strong> such as
<code>label.name</code>. Runtime-only fields like
<code>label.display_value</code> exist only in the API response and
<strong>cannot</strong> be used in query conditions; such filters will be ignored by
the ServiceNow query engine.</p>

<p>The API response includes human-readable label values because
<code>sysparm_display_value=true</code> is always applied by this endpoint.</p>
]]>
			</Desc>

			<Code>
				<![CDATA[
-- 1. Get ALL labels (tags) for a specific Problem record
SELECT *
FROM get_record_labels
WITH(
	ParentTableName='problem',
	ParentSysId='62304320731823002728660c4cf6a7e8'
)

-- 2. Check whether the record has a specific label
SELECT *
FROM get_record_labels
WITH(
	ParentTableName='problem',
	ParentSysId='62304320731823002728660c4cf6a7e8',
	Query='label.name=trial'
)

-- 3. Get labels where the name starts with a prefix (e.g. odbc*)
SELECT *
FROM get_record_labels
WITH(
	ParentTableName='problem',
	ParentSysId='62304320731823002728660c4cf6a7e8',
	Query='label.nameSTARTSWITHodbc'
)

-- 4. Get labels where the name contains a keyword
SELECT *
FROM get_record_labels
WITH(
	ParentTableName='problem',
	ParentSysId='62304320731823002728660c4cf6a7e8',
	Query='label.nameLIKEpower'
)

-- 5. Get labels added by a specific user
SELECT *
FROM get_record_labels
WITH(
	ParentTableName='problem',
	ParentSysId='62304320731823002728660c4cf6a7e8',
	Query='sys_created_by=admin'
)

-- 6. Get labels added in the last 7 days
SELECT *
FROM get_record_labels
WITH(
	ParentTableName='problem',
	ParentSysId='62304320731823002728660c4cf6a7e8',
	Query='sys_created_on>=<<today-7d,FUN_TO_DATETIME>>'
)

-- 7. Combine multiple filters and order by most recent label
SELECT *
FROM get_record_labels
WITH(
	ParentTableName='problem',
	ParentSysId='62304320731823002728660c4cf6a7e8',
	Query='label.nameLIKEtrial^sys_created_by=admin^ORDERBYDESCsys_created_on'
)
		]]>
			</Code>
		</Example>


		<Example Group="ODBC" Slug="read-table-row-count" Label="Read table row count">
			<Desc>
				<![CDATA[
<p>This example demonstrates how to retrieve the total number of rows in a ServiceNow table
using the <code>get_table_row_count</code> endpoint.</p>

<p>The row count is calculated <strong>server-side</strong> using
<code>sysparm_count=true</code>, which is significantly faster and more efficient than
downloading records and counting them client-side.</p>

<p>You can optionally apply a server-side filter using the <code>Query</code> parameter
to count only matching rows (for example, high-priority incidents or active records).</p>
		]]>
			</Desc>

			<Code>
				<![CDATA[
-- Count ALL records in the Incident table
-- Uses server-side counting (no data rows are downloaded)
SELECT count
FROM get_table_row_count
WITH(
	TableName='incident'
)

-- Count only HIGH PRIORITY incidents (priority = 1)
-- The Query parameter applies an encoded ServiceNow filter before counting
SELECT count
FROM get_table_row_count
WITH(
	TableName='incident',
	Query='priority=1'
)
				]]>
			</Code>

		</Example>

	</Examples>
</ApiConfig>