https://api-sb.globalwolfweb.com
The Lone Wolf WolfConnect API is a collection of RESTful web resources allowing third parties access to data.
Index
- Authentication
- Creating a Request
- Creating the Signature for the Authorization Header
- Handling a Response
- Handling Time Zones
- Supported Data Formats
- Compression
- OData Support
- Creating and Updating Data
- Concurrency Checking
- Permissions
- Error Codes
APIs in this documentation: Members, Transactions, Classifications, Conditions, Contact Types, Property Types, Sources of Business.
The Lone Wolf API is a language independent resource and will work with such languages as Java, JavaScript, PHP and .NET.
The base URL for all calls to the production version of the API is https://api.globalwolfweb.com. The base URL for all calls to the test version of the API is https://api-sb.globalwolfweb.com.
Authentication
Authentication begins with a consumer key, secret key, and an API token key, which will be provided by Lone Wolf Technologies.
The secret key is a string of characters used to seed or salt the signature of all requests made to the API. The secret key should be guarded in the same way you would guard your bank account password.
Creating a Request
To properly authenticate an API request, there are 2 headers that must be added: Authorization and Content-MD5.
Authorization Header
The Authorization header will be of the form:
Authorization: [Scheme] [Authorization String]
The scheme portion of the Authorization header tells the API how it should authenticate the request by telling the API how to interpret the authorization string portion of the header. The authorization string is a series of strings separated by a colon.
Authorization: LoneWolfKey [Consumer Key]:[Signature]:[Date]
| Part | Description |
|---|---|
| Consumer Key | Your consumer key provided to you by Lone Wolf. |
| Signature | The signature for the request (detailed below). |
| Date | A string representing the UTC date and time of the request in the format specified below. |
The LoneWolfKey authorization scheme will be used when calling resources that deal with your API account.
Authorization: LoneWolfToken [API Token]:[Client Code]:[Signature]:[Date]
| Part | Description |
|---|---|
| API Token | The API token is provided by Lone Wolf. |
| Client Code | The code given to the office or office family that the request will pertain to. |
| Signature | The signature for the request (detailed below). |
| Date | A string representing the UTC date and time of the request in the format specified below. |
The LoneWolfToken authorization scheme will be used when calling resources that access your actual data.
There is never a scenario where you would send more than one type of authorization scheme.
Authorization Header Date and Time Format
The date and time format for any date specified in the Authorization header is:
[4 digit year]-[2 digit month starting at 01 for January]-[2 digit day of the month starting at 01]-[2 digit hour in 24 hour format from 00-23]-[2 digit minute from 00-59]-[2 digit second from 00-59]-[3 digit millisecond from 000-999][Single letter time zone for UTC]
The actual string should all be on one line with a dash separating each part of the date/time. The Z at the end of the string represents the UTC time zone.
To format the date in .NET, use the string yyyy-MM-dd-HH-mm-ss-fffK.
To format the date in Java, use the string yyyy-MM-dd-HH-mm-ss-SSSX.
TIP: If the language you are working with does not support milliseconds, use 000 every time.
For example, the date January 1st, 2014 at 3:45:33.554 PM EST would be represented as:
2014-01-01-20-45-33-554Z
Notice that the hour portion of the string has been changed from Eastern to Greenwich Mean Time.
Content-MD5 Header
The Content-MD5 header holds the base 64 encoded MD5 hash of the body of the request as described by the HTTP specification for normal PUT and POST requests.
However not all requests will have a body: for instance, GET or DELETE requests. When this is the case the Content-MD5 header should only contain the base 64 encoded MD5 hash of an empty string:
Content-MD5: 1B2M2Y8AsgTpgAmY7PhCfg==
Another circumstance in which the value for the Content-MD5 header is different is when a multipart request is made. Multipart requests will be used when streaming files to the API. The base 64 encoded MD5 hash of an empty string should be used for multipart requests as well.
To ensure generation of the correct value for the Content-MD5 header it is good practice setting the body of the request then passing the body of the request into a function that will perform the hash. This will ensure that what you put in the request is the exact same thing you are using to create the hash.
private string CreateContentMD5Header(string bodyContent)
{
byte[] md5 = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(bodyContent));
return Convert.ToBase64String(md5);
}
A common mistake when generating the Content-MD5 header is base 64 encoding a string representation of the MD5 hash. You must keep the MD5 hash as a byte array and then base 64 encode that byte array.
Creating the Signature for the Authorization Header
The signature portion of the Authorization header is the HMACSHA256 hash of the following string:
[HTTP Method]:[Resource URI]:[Date]:[Content-MD5]
| Part | Description |
|---|---|
| HTTP Method | The HTTP method. GET, PUT, POST, DELETE. |
| Resource URI | The non URL encoded resource URI without the host name. This must start with a slash and does not include the https://api.globalwolfweb.com portion. |
| Date | A string representing the UTC date and time of the request in the format specified above. This should be the same string that is used in the Authorization header. |
| Content-MD5 | The value in the Content-MD5 header. |
For example, to get the data for a transaction with id WVnG90WFTSK2g9d_L7yd6g== on January 1st, 2014 at 3:45:33.554 PM EST, the signature string to hash would be:
GET:/wolfconnect/transactions/v1/WVnG90WFTSK2g9d_L7yd6g==:2014-01-01-20-45-33-554Z:1B2M2Y8AsgTpgAmY7PhCfg==
Notice that the time string has been changed from EST to UTC. The Content-MD5 portion of the string to hash is the base 64 encoded MD5 hash of an empty string since this is a GET request.
You need to first create this string for the requested resource and then use your secret key to seed the HMACSHA256 hash function. The value that comes back would then be used as the signature for the Authorization header.
string stringToHash = "GET:/wolfconnect/transactions/v1/WVnG90WFTSK2g9d_L7yd6g==:2014-01-01-20-45-33-554Z:1B2M2Y8AsgTpgAmY7PhCfg==";
var hasher = new HMACSHA256(Encoding.UTF8.GetBytes([Your Secret Key]));
byte[] bytes = hasher.ComputeHash(Encoding.UTF8.GetBytes(stringToHash));
StringBuilder signature = new StringBuilder();
foreach(byte b in bytes)
{
signature.AppendFormat("{0:x2}", b);
}
// The signature variable now contains the value to use in the Authorization header.
URL Encoding
If you URL encode the above resource URI, you would get:
/wolfconnect/transactions/v1/WVnG90WFTSK2g9d%5fL7yd6g%3d%3d
This is perfectly valid when making the request to the API. However, when constructing the string to hash for the signature, the Resource URI must not be URL encoded.
Using a different Hash Algorithm
The default hash algorithm is HMACSHA256. However, the API also supports the use of HMACSHA384 and HMACSHA512 if you wish to increase security. To tell the API that you wish to use a different hash algorithm simply append it to the authorization scheme portion of the Authorization header separated by a dash.
Authorization: LoneWolfToken-HMACSHA512 [Authorization string]
Hash Examples
The following tables list HMAC SHA hashes for the specified strings. The table is there for your convenience to make sure you have your hashing algorithm code correctly setup. All hashes were created with the seed (or secret key in the context of the API) LoneWolf.
Hash of the string Lone Wolf Real Estate Technologies:
| Algorithm | Hash |
|---|---|
| HMACSHA256 | cc62f4a577cd76277a97018bf7b476fc911823fac1cdc4ea3f672e8d4b84bac2 |
| HMACSHA384 | 95d1805b87daf9f6259cec06a20c8051dd5894a160e7af2d1a371569a6fa5fcb7a0be67e825486e27d42d6b2e71829c1 |
| HMACSHA512 | 814e10262e8bf47dcd103dabca0e44736e902beb15b1a10c561fcb3818d9d6b7c2eeb076b1c4d9a4f9d90909e406028066683a92ca2a6deec186aec456993342 |
Hash of the string The Complete Enterprise Solution:
| Algorithm | Hash |
|---|---|
| HMACSHA256 | 358cde6aeb0cfb0750665e9b54efbaca1665621a0d7c71a2184fcf6e5c022c8f |
| HMACSHA384 | 2936f83a7c1aff99fea0deefec6039c483834d74c7f3adf0e6e2854319b14592c588c7266dc2f4df5d8854a272ee59ba |
| HMACSHA512 | 0d1c669ddd64f5bb1bc1d8377f8297f0f8a32416e69f4943a7883ad6dc9582229ebbde6eac037dedce85e408ec8b006c58f57ebde7e71182bf7318da19e910d8 |
Handling a Response
Lone Wolf API responses use the standard HTTP status codes to tell you how you should handle the content of the response. In general, there are 2 types of responses. Success and Error responses. Success responses will use the HTTP status codes OK (200) and Created (201). All other status codes indicate an error.
Typically when a success message is received the response content will contain an object that relates to the accessed resource. When an error response is received it will contain a ClientError object. This object will contain its own Code value that will represent the problem that caused the error response. This means that you can use the standard HTTP response code to handle the error or ignore it all together and use the Lone Wolf Code to handle the error.
Handling Time Zones
Time zones must be handled correctly as the API can return and accept dates with times. To make it easy all dates with times returned from the API will be sent back in UTC time. As a corollary, all dates and times sent to the API must include the time zone offset. If the time zone is not specified, UTC time is assumed.
The individual resource documentation will specify the type of date the property is. You do not have to perform the UTC conversion if it is just a date; the time portion of the Date property will be ignored if specified.
Supported Data Formats
The API supports JSON and XML data formats. Each individual API section has the definitions for the objects that it supports. These object definitions can be used to create classes in any language that can then be serialized to JSON or XML and passed to the API. The response from the API can then be deserialized into these same objects.
Date and Timestamp Properties
Date and Timestamp properties have slight differences in how the API is expecting them. Dates are in the following format (all on one line) for both JSON and XML formats:
[4 digit year]-[2 digit month starting at 01]-[2 digit day of the month starting at 01]
.NET format string: yyyy-MM-dd — Java format string: yyyy-MM-dd
If you pass the time to the API during an update for a Date property it will be ignored when saving it to the database.
A Timestamp value should be in ISO 8601 or Round-trip format (all on one line):
[4 digit year]-[2 digit month starting at 01]-[2 digit day of the month starting at 01]T[2 digit hour between 00-23]:[2 digit minute between 00-59]:[2 digit second between 00-59].[7 digit sub-second between 0000000-9999999]%2B00:00
.NET format string: yyyy-MM-dd'T'HH:mm:ss.fffffffK — Java format string: yyyy-MM-dd'T'HH:mm:ss.SSSXXX
NOTE: The Java SimpleDateFormat class does not handle more than 3 sub-seconds. As of Java 7, you can use javax.xml.bind.DatatypeConverter.parseDateTime(timestampString) to get a Calendar object back. You do not need to specify the format in the DatatypeConverter.parseDateTime() function. If using Java 6 or earlier, you will have to write your own parser to handle the timestamp returned from the API. The above format should be used when sending a timestamp value to the API in any Java version.
Timestamp values will always be in UTC time when retrieved from the API and must always specify the time zone when updating a time. If no time zone is specified, the API will assume UTC time.
Compression
The API supports gzip and deflate compression of the request and response. If you plan to send compressed requests to the API, make sure that the Content-Encoding request header is included and holds the type of compression used. If you want compressed responses, include the Accept-Encoding request header for the type of compression you support.
NOTE: Compressed Multi-part requests are not supported at this time.
OData Support
The API supports OData style filtering for resources using the HTTP GET method. OData is a standard query string language used for filtering resources on REST APIs. Much more detailed information can be found at www.odata.org. The API currently supports the OData 4.0 specification for URL conventions but does not support the full range of query parameters.
Supported OData Parameters
If any parameter is not supported for a particular resource it will be noted in that resource's documentation. Otherwise it is safe to assume that all of these parameters are supported for all resources using the GET HTTP method.
| Parameter | Description |
|---|---|
| $filter | Filters data on properties related to the resource. NOTE: Only Logical, Arithmetic and Grouping operators are currently supported. No Canonical functions are currently supported (contains, endswith, startswith, etc.). |
| $orderby | Orders the objects returned in the response by a property related to the resource. |
| $top | Returns the specified top number of records for the given query. $orderby must be specified for $top to be used. |
| $skip | Skips the specified number of records before returning the results. $orderby must be specified for $top to be used. |
| $search | Allows for free form text to be searched. Each API will note which fields are included in the free form search when this parameter is available. |
| $expand | Instructs the API to include a child object or collection in the response. Please see the section below for more details on how to use this parameter. |
The maximum number of objects returned from any resource is 1,000. If the $top parameter is not passed in the query string, $top=1000 is assumed. If a value greater than 1,000 is specified an error will be thrown. If the response holds 1,000 objects, you must implement paging (described below) to make sure you retrieve all the records.
Only the $expand OData query parameter is supported for resources that return one specific object rather than allow you to filter many objects; all other OData query parameters will be ignored.
Usage of the $expand Query Parameter
The $expand parameter is used a little differently than the OData specification: if the $expand parameter is omitted from the query string then ALL child objects and collections will be returned. In the case of a Transaction object this would mean that the Tiers, ClientContacts, BusinessContacts, Classification, etc. child objects and collections will also be returned (provided you have permission to see those objects). If you want to return only the Transaction object pass in $expand= in the query string (the $expand parameter but with no values specified).
The reason for this difference is to maintain backward and forward compatibility. Before OData support, calls to the Transactions Resource had no way to tell the API to return only specific objects of a Transaction so the entire object including any child objects would be returned. Returning the full object maintains forward compatibility so if a new child object or collection is added to the Transaction object then not passing the $expand parameter will include the new child object or collection automatically. If you wish to only return the Transaction object and are already passing in $expand= in the query string then the new object or collection will still not be returned to you.
Implementing Paging
The $top and $skip query parameters can be used to implement paging for a given resource. However, each call to the API performs a new query so there is a chance that new records could be inserted or values updated between each API call.
Examples
The following URL returns transactions created on or after April 1st, 2014 (the full transaction object is returned because the $expand parameter is omitted):
/wolfconnect/transactions/v1?$filter=CreatedTimestamp ge datetimeoffset'2014-04-01T00:00:00Z'
The following URL returns the top 10 transactions with the highest sell price (only the Transaction objects are returned because the $expand parameter is specified but empty):
/wolfconnect/transactions/v1?$top=10&$orderby=SellPrice desc&$expand=
The following URL returns the transaction with id 98agdji99jasdof908==. The Transaction object returned will include the ClientContacts and BusinessContacts. Classification, PropertyType, Tiers, etc. will all be null:
/wolfconnect/transactions/v1/98agdji99jasdof908==?$expand=ClientContacts,BusinessContacts
Creating and Updating Data
Creating and updating data with the API is pretty straight forward. If you set a property to a value the corresponding property in the database will be set to that value.
However NULL-valued properties are handled differently. When creating a new record with a NULL-valued property its default value will be saved in the database. The default value will be returned to you in the response. When updating an existing record its current value will NOT be updated in the database and the original value will be returned to you in the response.
The other way to use the default value when creating data is to not send the property in the request at all. This also works when attempting to not update the current value when updating. We allow the use of NULL for this scenario to ease creating classes that can be serialized to a request.
There is one caveat to this rule: if a NULL value is an acceptable value for a given property then the NULL value will be saved in the database. Get the API to use the default value when creating data by not sending that property in the request at all. This also works when attempting to not update the existing value when updating. This will occur most often with Date, DateTime and Numeric data but it is possible for String data as well.
An example of this would be the Member.InactiveDate property: having a NULL value for the InactiveDate is valid and indicates that the member is still active. If you were using the Members Resource to update data for a member that is inactive, you have two options: send the value currently stored for InactiveDate (effectively updating it to the same value) or do not include the InactiveDate property in the request at all.
These types of properties are noted in the object definitions by the word (Nullable) in the property description. If you see a property described as (Nullable) then you know you must handle the property in this special way.
Collection Properties (Lists and Arrays)
Collection properties will typically hold "child" records of a given parent object. If the property that holds a collection is null the current values for that collection are not changed. If the property is not sent in the request at all the current values are not updated. Send an empty collection to delete the collection for the given property. If the current state of the database had 3 items for a given collection but you only wanted to keep 1 of them, then you would send a collection containing only the one you wanted to keep; the other 2 items would be deleted.
For example, if you were updating a transaction but did not want to update the conditions associated to that transaction, simply set the Transaction.Conditions property to NULL or do not send that property in the request. If you wanted to delete all of the conditions from a transaction, you would set the Transaction.Conditions property to an empty collection. If the transaction had 3 conditions currently associated to it but you only wanted to keep the second one then you would set the Transaction.Conditions property to a collection containing only the second condition; conditions 1 and 3 would then be deleted.
Object Properties
Object properties will typically hold an associated "child" object. They will have 2 properties associated to them. One for the Id of the object and the other for the object itself. When creating or updating an Object property you only need to send the Id property. The object property will be returned to you in the response.
For example: ClientContact objects. The ClientContact object has 2 properties for source of business. The ClientContact.SourceOfBusinessId property is of type string and holds the Lone Wolf Id for the source of business. The ClientContact.SourceOfBusiness property is of type SourceOfBusiness and holds the source of business object.
When creating or updating a ClientContact object you only need to pass the SourceOfBusinessId value to the API. Whatever value is in ClientContact.SourceOfBusiness is ignored. However ClientContact.SourceOfBusiness will be available in the response and will reflect the source of business record for the sent SourceOfBusinessId. Set the SourceOfBusinessId value to NULL to leave the current source of business for a given ClientContact object. Send an empty string for SourceOfBusinessId to remove the source of business record from the ClientContact object.
String Properties
String properties are no different than any other property in how they behave but since NULL is such a common value for a string property they deserve their own section. Set the string property to NULL or do not pass the string property in the request to use the default value when creating or keep the current value when updating. You must send an empty string for the property if you wish to clear the corresponding value in the database.
For example, if you were updating data for a given member and did not want to change the current value for the middle name, send NULL for Member.MiddleName or leave it out of the request all together. If the current value was "Anne" and you wanted to clear it then you would set Member.MiddleName to an empty string.
Concurrency Checking
The API supports concurrency checking. It is strongly recommended that you implement concurrency checking whenever updating data through the API as it will eliminate the possibility of overwriting someone else's changes. Let's take the following scenario:
- A transaction is retrieved using the API and stored in a third party database. The close date for this transaction is 01/01/2015 and the price is $100,000.
- A user opens up that same transaction on the EDS page in WOLFconnect and changes the price to $110,000.
- The same transaction is then updated using the API. The API call changes the close date to 01/05/2015 but in doing so sends the price that it knows about which is $100,000. The user's change in WOLFconnect has just been overwritten.
There are 2 ways to avoid this scenario. The first is to only send the data that you want updated in the request. If you just want the close date updated, only set the Transaction.CloseDate property and leave the other properties as null or exclude them from the request all together.
The second way is to use the RowVersion property on the Transaction object. Any object that supports concurrency checking will have a RowVersion property associated to it. The RowVersion property holds the version of a particular record in the database. In the same scenario above, if the RowVersion was passed in the update in Step 3, it would not match the row version currently stored in the database. The API call would then fail with a Conflict HTTP Status.
NOTE: If the RowVersion property is passed to the API as NULL, no concurrency check will take place and the data passed in the API call will be updated in the database.
Concurrency checking may not need to be used in every scenario but there is no downside to implementing it. If there is even the slightest chance that data could be overwritten, it is strongly recommended that you implement concurrency checking.
Permissions
Lone Wolf has the ability to set read and edit permissions on a property-by-property basis for any object. Attempting to create or delete an object for which you do not have permission will return an error. Attempting to update a value for which you do not have permission will return an error. Retrieving an object without read permission for a given property will be NULL in the response.
Collection properties will contain an empty collection if you do have read permission but no objects exist. For example, if you do not have read permission for the Transaction.Conditions property it will always be passed back in the response as NULL.
If you have read permission for object properties but no object exists then the Id property will be an empty string and the object property will be NULL. For example, if you do not have read permission for the ClientContact.SourceOfBusiness property the ClientContact.SourceOfBusinessId and ClientContact.SourceOfBusiness properties will both be null in the response. If you have read permission but the source of business is not set for the ClientContact then ClientContact.SourceOfBusinessId will be set to an empty string and the ClientContact.SourceOfBusiness property will be null.
With this in mind, if you are retrieving data from the Lone Wolf API to update your own system and the data comes back as NULL DO NOT update your own system with a NULL value. A NULL value will typically mean that you do not have access to that property.
The same exception applies to this rule as when updating certain values: if you do have access to a given property but NULL is a valid value for that property then NULL will be returned in the response. If NULL is a valid value for a property but you do not have read permission to that property then the property will not be included in the response.
Error Codes
The ClientError object is used to give detailed information whenever an API request fails. This is the object that will be sent back in the response. If you perform a request that returns with an error and the response does not contain a ClientError object it is a good indication that you are using the wrong URL.
| Code | Description |
|---|---|
| 1000 | Unknown error. This is typically accompanied with an Internal Server Error HTTP status code (500). Please contact Lone Wolf support if you receive this error. |
| 1001 | Invalid Parameter. |
| 1002 | Missing Parameter. |
| 1003 | The request must be a multipart request. |
| 1004 | No files were sent with the request. |
| 1005 | The maximum files allowed for the request was exceeded. |
| 1006 | Validation failed when trying to save a resource. This will occur when a requirement for the data passed to the API has not been met. |
| 1007 | Member authentication failed. This will occur when a member tries to log in but has been deactivated or they have not finished resetting their password. |
| 1008 | Invalid Operation. You most likely don't have access to perform said operation. |
Responses for the standard HTTP status codes of BadRequest (400), Unauthorized (401), NotFound (404) and Conflict (409) will all have an object of type ClientError sent back in the response. If they do not then that is a good indication that the URL you are accessing is invalid. For generic BadRequest, Unauthorized, NotFound and Conflict responses the ClientError Code property will be the same as the HTTP status code.
This is version 1.0.0 of this API documentation. Last update on Jul 10, 2026.