Responses and errors
Every Transactional API call returns HTTP 200 with a response envelope. How to tell success from failure, and what each error means.
ResponseState.The response envelope
Every operation returns the same envelope, named {Operation}Result (for example GetCustomersModifiedSincePagedResult):
The outcome of the call. Check this first.
| Value | Meaning |
|---|---|
Success | The call worked. The result is in Return. |
Invalid | The request was understood but rejected by a business rule (for example a required field is missing). The reasons are in Messages. |
Error | The call failed (for example the token expired, or an unexpected error occurred). The reason is in ErrorCode and Messages. |
The error code when ResponseState is not Success. 0 on success. See Error codes.
Messages about the call. Each has a Message (text), a Severity and an ErrorCode.
The result. Always a list, also for operations that return one object: read the first item. Empty when the call failed, and also when it succeeded but found nothing.
The type of the objects in Return, for example Customer.
true for paged operations.
Paged operations only: the number of pages for the whole result, with the pageSize you sent.
The operation and parameters as the server received them. Useful for debugging; you do not need to read it.
Related data in Details
Many objects carry a Details property with the related data you usually need next to the object, so you do not have
to fetch it in separate calls. For example, a customer's Details holds its status, industry, currency and owners as
objects with their IDs. Each operation page describes the Details of the objects it returns.
Checking the result in code
Check in this order: the HTTP status (a SOAP fault, see below), then ResponseState, then Return.
import xml.etree.ElementTree as ET
API = "{http://api.timelog.com}"
def parse_result(response):
"""Return the items of `Return`, or raise with the API's own error code and message."""
if response.status_code != 200:
# SOAP fault: the request itself was wrong (SOAPAction, namespace, malformed XML)
raise RuntimeError(f"SOAP fault (HTTP {response.status_code}): {response.text[:500]}")
root = ET.fromstring(response.content)
state = root.find(f".//{API}ResponseState").text
if state != "Success":
code = root.find(f".//{API}ErrorCode").text
messages = [m.find(f"{API}Message").text
for m in root.iter(f"{API}APIMessage")
if m.find(f"{API}Severity").text != "Message"]
raise RuntimeError(f"{state} ({code}): {'; '.join(messages)}")
returned = root.find(f".//{API}Return")
return list(returned) if returned is not None else []
Example: a failed call
This response was recorded from a real call to GetCustomersModifiedSincePaged with an expired token. Note that the
HTTP status is 200, but ResponseState is Error and ErrorCode is 20004.
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<GetCustomersModifiedSincePagedResponse xmlns="http://api.timelog.com/services/crm/1_4">
<GetCustomersModifiedSincePagedResult xmlns:a="http://api.timelog.com" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:Return/>
<a:ReturnTypeDescription>Customer</a:ReturnTypeDescription>
<a:Request>…</a:Request>
<a:ResponseState>Error</a:ResponseState>
<a:Messages>
<a:APIMessage>
<a:Message>Token has Expired!</a:Message>
<a:Severity>Error</a:Severity>
<a:ErrorCode>20004</a:ErrorCode>
</a:APIMessage>
<a:APIMessage>
<a:Message>Duration of call was 0,0010687 sec.</a:Message>
<a:Severity>Message</a:Severity>
<a:ErrorCode>0</a:ErrorCode>
</a:APIMessage>
</a:Messages>
<a:ErrorCode>20004</a:ErrorCode>
<a:IsReturnPaged>true</a:IsReturnPaged>
<a:TotalPageCount>0</a:TotalPageCount>
</GetCustomersModifiedSincePagedResult>
</GetCustomersModifiedSincePagedResponse>
</s:Body>
</s:Envelope>
The Request block is shortened here.
Error codes
These codes can come back from any operation. Each operation page lists the errors specific to it.
| ErrorCode | ResponseState | Message | What it means | What to do |
|---|---|---|---|---|
| 20004 | Error | Token has Expired! | The token is more than 12 hours old. | Call GetToken again and repeat the call. |
| 20003 | Error | Token could not be validated! | The token was issued for another account, or one of its values was changed. | Send the token's three values back unchanged. |
| 20008 | Error | API is not Activated: Please Enable | The Transactional API is not enabled for this account. | Ask your TimeLog administrator. Retrying does not help. |
| 20009 | Error | Only secure access is allow in TLP. API must be called via secure endpoint(https). | The call did not use the secure endpoint. | Call the …ServiceSecure.svc URL over HTTPS. |
| 40001 | Error | Error during call on TimeLog.API, Message 'Object reference not set to an instance of an object.' | The token element is missing from the call. | Add the token as the last parameter. |
| 40001 | Error | Error during call on TimeLog.API, Message '…' | A general error. The real reason is the text inside Message '…': for example a missing token, a missing permission, or invalid data. | Read the embedded message. The operation page lists the messages it can produce. |
Message '.SOAP faults: when it is not a 200
A few errors happen before the request reaches TimeLog's code. They come back as a SOAP fault with an HTTP error status (typically 500) instead of a response envelope:
- The
SOAPActionheader does not match an operation of the endpoint you called. Each service version has its own SOAPAction values: copy them from the operation page. - The XML is malformed, or an element is in the wrong namespace.