Skip to content

Instantly share code, notes, and snippets.

@davidlumley
Last active March 23, 2020 18:42
Show Gist options
  • Save davidlumley/5633664 to your computer and use it in GitHub Desktop.
Save davidlumley/5633664 to your computer and use it in GitHub Desktop.
Collection of XML requests and responses from AutoTasks SOAP API
=begin
======
example Savon client for connecting to AutoTask's SOAP API
- install savon via `gem install savon`
- ensure AUTOTASK_USERNAME and AUTOTASK_PASSWORD environment variables are set
=====
=end
require 'rubygems'
require 'savon'
AUTOTASK_WSDL = 'https://webservices2.autotask.net/atservices/1.5/atws.wsdl'
AUTOTASK_USERNAME = ENV['AUTOTASK_USERNAME']
AUTOTASK_PASSWORD = ENV['AUTOTASK_PASSWORD']
def autotask_client
@autotask_client ||= Savon::Client.new(
:wsdl => AUTOTASK_WSDL,
:basic_auth => [
AUTOTASK_USERNAME,
AUTOTASK_PASSWORD,
],
:raise_errors => false,
:log_level => :debug,
:log => true,
)
end
###
# returns 200, expected response body
#
autotask_client.call(:get_zone_info, :message => {
'UserName' => AUTOTASK_USERNAME,
})
##
# returns 200, expected response body
#
autotask_client.call(:get_entity_info, :message => {
'UserName' => AUTOTASK_USERNAME,
})
##
# empty queryxml, should return 400 (or similar) with errors
# returns 200, error in response body
#
# <ReturnCode>-1</ReturnCode>
# <EntityResults /><EntityResultType />
# <Errors>
# <ATWSError><Message>Root element is missing.</Message></ATWSError>
# <ATWSError><Message>Error reading in Query XML.</Message></ATWSError>
# </Errors>
# <EntityReturnInfoResults />
autotask_client.call(:query, :message => {
'sXML' => {
:queryxml => {}
}
})
##
# contains valid queryxml, should return 200 and entities
# doesn't work, returns 400
#
# empty response body
#
autotask_client.call(:query, :message => {
'sXML' => {
:queryxml => {
:entity => 'Contact',
:query! => '<condition><field>id<expression op="greaterthan">0</expression></field></condition>', # use ! to prevent escaping of internal fields
}
}
})
# Testing the create method to create account notes.
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<create xmlns="http://autotask.net/ATWS/v1_5/">
<Entities>
<Entity type="AccountNote">
<AccountID>29683561</AccountID>
<AssignedResourceID>29684288</AssignedResourceID>
<ActionType>4</ActionType>
<StartDateTime>2013-07-08 05:48:55</StartDateTime>
<EndDateTime>2013-07-15 05:48:55</EndDateTime>
<Name>Note 1</Name>
<Note>This is the first note.</Note>
</Entity>
<Entity type="AccountNote">
<AccountID>29683561</AccountID>
<AssignedResourceID>29684288</AssignedResourceID>
<ActionType>4</ActionType>
<StartDateTime>2013-07-08 05:48:55</StartDateTime>
<EndDateTime>2013-07-15 05:48:55</EndDateTime>
<Name>Note 2</Name>
<Note>This is the second note.</Note>
</Entity>
<Entity type="AccountNote">
<AccountID>29683561</AccountID>
<AssignedResourceID>29684288</AssignedResourceID>
<ActionType>4</ActionType>
<StartDateTime>2013-07-08 05:48:55</StartDateTime>
<EndDateTime>2013-07-15 05:48:55</EndDateTime>
<Name>Note 3</Name>
<Note>This is the last note.</Note>
</Entity>
</Entities>
</create>
</soap:Body>
</soap:Envelope>
-----
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<soap:Fault>
<faultcode>soap:Client</faultcode>
<faultstring>System.Web.Services.Protocols.SoapException: Server was unable to read request. ---&gt; System.InvalidOperationException: There is an error in XML document (4, 63). ---&gt; System.InvalidOperationException: The specified type is abstract: name='Entity', namespace='http://autotask.net/ATWS/v1_5/', at &lt;Entity xmlns='http://autotask.net/ATWS/v1_5/'&gt;.
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReader1.Read5_Entity(Boolean isNullable, Boolean checkType)
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReader1.Read132_create()
at Microsoft.Xml.Serialization.GeneratedAssembly.ArrayOfObjectSerializer92.Deserialize(XmlSerializationReader reader)
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
--- End of inner exception stack trace ---
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle)
at System.Web.Services.Protocols.SoapServerProtocol.ReadParameters()
--- End of inner exception stack trace ---
at System.Web.Services.Protocols.SoapServerProtocol.ReadParameters()
at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()</faultstring>
<detail />
</soap:Fault>
</soap:Body>
</soap:Envelope>
# Testing the creation of entities using raw soap request
<?xml version="1.0" encoding="utf-16"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<create xmlns="http://autotask.net/ATWS/v1_5/">
<Entities>
<Entity xsi:type="AccountNote">
<AccountID>29683561</AccountID>
<ActionType>3</ActionType>
<AssignedResourceID>29684288</AssignedResourceID>
<EndDateTime>2013-07-15 05:48:55</EndDateTime>
<Name>Note 2</Name>
<Note>This is the second note.</Note>
<StartDateTime>2013-07-08 05:48:55</StartDateTime>
</Entity>
</Entities>
</create>
</soap:Body>
</soap:Envelope>
----------
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<queryResponse xmlns="http://autotask.net/ATWS/v1_5/">
<queryResult>
<ReturnCode>-1</ReturnCode>
<EntityResults />
<EntityResultType />
<Errors>
<ATWSError>
<Message>Object reference not set to an instance of an object.</Message>
</ATWSError>
<ATWSError>
<Message>Error reading in Query XML.</Message>
</ATWSError>
</Errors>
<EntityReturnInfoResults />
</queryResult>
</queryResponse>
</soap:Body>
</soap:Envelope>
# Example from https://webservices2.autotask.net/atservices/1.5/atws.asmx?op=query
# I assume the contents of the `sXML` attribute are the `queryxml`
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Header>
<AutotaskIntegrations xmlns="http://autotask.net/ATWS/v1_5/">
<PartnerID>string</PartnerID>
</AutotaskIntegrations>
</soap12:Header>
<soap12:Body>
<query xmlns="http://autotask.net/ATWS/v1_5/">
<sXML>string</sXML>
</query>
</soap12:Body>
</soap12:Envelope>
# Correctly runs GetEntityInfo and returns a list of entities
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="http://autotask.net/ATWS/v1_5/" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Body>
<tns:GetEntityInfo></tns:GetEntityInfo>
</env:Body>
</env:Envelope>
# Correctly returns the appropriate zone to use
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="http://autotask.net/ATWS/v1_5/" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Body>
<tns:getZoneInfo>
<tns:UserName>cheartbeat@ClientHeartbeatDemo.com</tns:UserName>
</tns:getZoneInfo>
</env:Body>
</env:Envelope>
# Responds with HTTP 400, empty body
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="http://autotask.net/ATWS/v1_5/" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Body>
<tns:query>
<tns:sXML>
<tns:queryxml>
<tns:entity>Contact</tns:entity>
<tns:query>
<field>id
<expression op="greaterthan">0</expression></field>
</tns:query>
</tns:queryxml>
</tns:sXML>
</tns:query>
</env:Body>
</env:Envelope>
# Experimenting with the XML structure yields no gains.
# Without `sXML`
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="http://autotask.net/ATWS/v1_5/" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Body>
<tns:query>
<queryxml>
<entity>Contact</entity>
<query>
<condition>
<field>id<expression op="greaterthan">0</expression></field>
</condition>
</query>
</queryxml>
</tns:query>
</env:Body>
</env:Envelope>
-----
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<queryResponse xmlns="http://autotask.net/ATWS/v1_5/">
<queryResult>
<ReturnCode>-1</ReturnCode>
<EntityResults />
<EntityResultType />
<Errors>
<ATWSError>
<Message>Object reference not set to an instance of an object.</Message>
</ATWSError>
<ATWSError>
<Message>Error reading in Query XML.</Message>
</ATWSError>
</Errors>
<EntityReturnInfoResults />
</queryResult>
</queryResponse>
</soap:Body>
</soap:Envelope>
-----
# Without `queryxml`
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="http://autotask.net/ATWS/v1_5/" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Body>
<sXML>
<queryxml>
<entity>Contact</entity>
<query>
<condition>
<field>id<expression op="greaterthan">0</expression></field>
</condition>
</query>
</queryxml>
</sXML>
</env:Body>
</env:Envelope>
-----
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<queryResponse xmlns="http://autotask.net/ATWS/v1_5/">
<queryResult>
<ReturnCode>-1</ReturnCode>
<EntityResults />
<EntityResultType />
<Errors>
<ATWSError>
<Message>Object reference not set to an instance of an object.</Message>
</ATWSError>
<ATWSError>
<Message>Error reading in Query XML.</Message>
</ATWSError>
</Errors>
<EntityReturnInfoResults />
</queryResult>
</queryResponse>
</soap:Body>
</soap:Envelope>
# Properly formed, and as per the documentation.
# Also fails.
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="http://autotask.net/ATWS/v1_5/" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Body>
<tns:query>
<sXML>
<queryxml>
<entity>Contact</entity>
<query>
<condition>
<field>id<expression op="greaterthan">0</expression></field>
</condition>
</query>
</queryxml>
</sXML>
</tns:query>
</env:Body>
</env:Envelope>
-----
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<queryResponse xmlns="http://autotask.net/ATWS/v1_5/">
<queryResult>
<ReturnCode>-1</ReturnCode>
<EntityResults />
<EntityResultType />
<Errors>
<ATWSError>
<Message>Object reference not set to an instance of an object.</Message>
</ATWSError>
<ATWSError>
<Message>Error reading in Query XML.</Message>
</ATWSError>
</Errors>
<EntityReturnInfoResults />
</queryResult>
</queryResponse>
</soap:Body>
</soap:Envelope>
# A properly formed request, with the `queryxml` as the body.
# This also fails as expected, the API document specified the `queryxml` should be contained within `query` and `sXML`
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="http://autotask.net/ATWS/v1_5/" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Body>
<queryxml>
<entity>Contact</entity>
<query>
<condition>
<field>id<expression op="greaterthan">0</expression></field>
</condition>
</query>
</queryxml>
</env:Body>
</env:Envelope>
-----
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<queryResponse xmlns="http://autotask.net/ATWS/v1_5/">
<queryResult>
<ReturnCode>-1</ReturnCode>
<EntityResults />
<EntityResultType />
<Errors>
<ATWSError>
<Message>Object reference not set to an instance of an object.</Message>
</ATWSError>
<ATWSError>
<Message>Error reading in Query XML.</Message>
</ATWSError>
</Errors>
<EntityReturnInfoResults />
</queryResult>
</queryResponse>
</soap:Body>
</soap:Envelope>
# As expected, using `queryxml` as the request fails with SOAP error.
<?xml version="1.0"?>
<queryxml>
<entity>Contact</entity>
<query>
<condition>
<field>id<expression op="greaterthan">0</expression></field>
</condition>
</query>
</queryxml>
-----
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Header>
<soap12:Upgrade xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:SupportedEnvelope qname="soap:Envelope" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" />
<soap12:SupportedEnvelope qname="soap12:Envelope" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope" />
</soap12:Upgrade>
</soap:Header>
<soap:Body>
<soap:Fault>
<faultcode>soap:VersionMismatch</faultcode>
<faultstring>
System.Web.Services.Protocols.SoapException: Possible SOAP version mismatch: Envelope namespace was unexpected. Expecting http://schemas.xmlsoap.org/soap/envelope/.
at System.Web.Services.Protocols.SoapServerProtocol.CheckHelperVersion()
at System.Web.Services.Protocols.SoapServerProtocol.ReadParameters()
at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()
</faultstring>
<detail />
</soap:Fault>
</soap:Body>
</soap:Envelope>
# Testing with use of CDATA ( http://stackoverflow.com/questions/5227333/xml-soap-post-error-what-am-i-doing-wrong/7628604#7628604 )
# All these SOAP requests are well formed according to the API documentation, not sure why it can't find the entity / queryxml.
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="http://autotask.net/ATWS/v1_5/" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Body>
<tns:query>
<sXML>
<![CDATA[<queryxml>
<entity>Contact</entity>
<query>
<field>id<expression op="greaterthan">0</expression></field>
</query>
</queryxml>]]>
</sXML>
</tns:query>
</env:Body>
</env:Envelope>
-----
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<queryResponse xmlns="http://autotask.net/ATWS/v1_5/">
<queryResult>
<ReturnCode>-1</ReturnCode>
<EntityResults />
<EntityResultType />
<Errors>
<ATWSError>
<Message>Object reference not set to an instance of an object.</Message>
</ATWSError>
<ATWSError>
<Message>Error reading in Query XML.</Message>
</ATWSError>
</Errors>
<EntityReturnInfoResults />
</queryResult>
</queryResponse>
</soap:Body>
</soap:Envelope>
@feens
Copy link

feens commented Apr 14, 2015

Very glad I bumped into this reference...doing some work with their API via Rails as well, and the documentation is considerably lacking. Glad you posted your findings.

@ZECTBynmo
Copy link

I still can't get past this error :(

@mikiwiik
Copy link

Excellent work, many thanks!!!

@aaronbartell
Copy link

I spent an inordinate amount of time getting this to work so I thought I'd post my results.

First, I learned it made a difference which web service end point I used. For some reason I was getting "Unhandled Exception" HTTP 500 errors when accessing https://webservices3.autotask.net/ATServices/1.5/atws.asmx but the same query and user/password works with https://webservices5.autotask.net/ATServices/1.5/atws.asmx.

I used SOAPUI to run the below query. Note you need to specify your AutoTask username/password in the HTTP Basic Auth portion of SOAPUI (I had tried to use the SOAP Header to make it work).

<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="http://autotask.net/ATWS/v1_5/" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
    <env:Body>
        <tns:query>
            <tns:sXML>
            <![CDATA[
            <queryxml>
              <entity>Contact</entity>
              <query>
                <field>id
                 <expression op="equals">13500304</expression></field>
              </query>
            </queryxml>
            ]]>
            </tns:sXML>
        </tns:query>
    </env:Body>
</env:Envelope>

@corydbrown
Copy link

Thank you all and @aaronbartell ! That query works for ticket IDs as well.

Using this CDATA and xmlns, how would you structure a create request. To create a TicketNote?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment