Search code examples
pythonwsdlsudsservicenow

How do I search a datetime range in servicenow with getRecords using suds?


I'm trying to do a Service Now query using suds, but I can't figure out how to specify a date range. Here is my code, it works for returning a record with an exact date:

from suds.client import Client

URL = 'https://blah.service-now.com/change_request.do?WSDL'
USERNAME = "blah"
PASSWORD = "blah"

client = Client(URL, username=USERNAME, password=PASSWORD)
result = client.service.getRecords(start_date = "2015-02-03 12:00:00")

print result

The printed result gives me a single record matching that exact datetime.

When I try start_date >= or start_date => or start_date >, they all say either "invalid syntax" or "NameError: name 'start_date' is not defined".

How do I "getRecords" for a time range?


Solution

  • Keep in mind the fact that you're basically just using suds to construct SOAP payloads. It helps to take step back and determine the SOAP request needed to get the response you're looking for.

    According to the WSDL, the start_date field accepts a single parameter, and behaves like blah=foo, so there's no way to specify ranges in that parameter:

    <xsd:element maxOccurs="1" minOccurs="0" name="start_date" type="xsd:string"/>
    

    What you probably want is the special "__encoded_query" parameter which accepts an encoded query string that you can construct using the filter builder UI in the ServiceNow web app:

    <xsd:element maxOccurs="1" minOccurs="0" name="__encoded_query" type="xsd:string"/>
    

    Let's say you want to query for all change_request records that have a start date within the month of October 2014. Go to the target ServiceNow instance (or any one, really, since the encoded query is going to be the same), and build your filter on /change_request_list.do: filter UI

    Now, right-click that blue filter and select "Copy query" to get the encoded query: enter image description here

    Here's the encoded query I generated:

    start_dateBETWEENjavascript:gs.dateGenerate('2014-10-01','00:00:00')@javascript:gs.dateGenerate('2014-10-31','23:59:59')
    

    Now, pass that as your __encoded_query parameter, with a payload that looks like this:

    <Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
        <Body>
            <getRecords xmlns="http://www.service-now.com/change_request">
                <__encoded_query xmlns="">start_dateBETWEENjavascript:gs.dateGenerate('2014-10-01','00:00:00')@javascript:gs.dateGenerate('2014-10-31','23:59:59')</__encoded_query>
            </getRecords>
        </Body> 
     </Envelope>
    

    So, to make suds work, just replace your start_date query with an __encoded_query query:

    from suds.client import Client
    
    URL = 'http://localhost:8080/change_request.do?WSDL'
    USERNAME = "admin"
    PASSWORD = "admin"
    
    client = Client(URL, username=USERNAME, password=PASSWORD)
    result = client.service.getRecords(__encoded_query = "start_dateBETWEENjavascript:gs.dateGenerate('2014-10-01','00:00:00')@javascript:gs.dateGenerate('2014-10-31','23:59:59')")
    
    print result