Tourwriter provides a standard API (Application Programming Interface) that allows your Tourwriter database and your website to automatically interact with each other. This can be used to provide data to and from your website (user will need to update their website to use this).
Table of contents
Introduction
Tourwriter provides REST API that lets you integrate your CRM, websites or automation platforms with third-party applications such as accounting, ERP, e-commerce, self-service portals and others.
The REST API uses simple HTTP methods such as GET, POST. These methods allow CRM data to be extracted in JSON format. This allows you to develop new applications and to integrate with existing business applications.
Authorization
Tourwriter uses basic auth (over SSL) which needs to be added to the header of each request.
Eg: Authorization: Basic Base64-encoded string of username:password
*Contact Tourwriter support at support@tourwriter.com for creating your API account
Suppliers
Overview
URL | https://api.tourwriter.com/suppliers |
Methods supported | GET |
Description | Retrieve suppliers |
Content-type | application/json |
GET Suppliers (Summarized)
Use this method to retrieve all suppliers with id and name
Url: https://api.tourwriter.com/suppliers
Optional parameters
search | To filter based on search term. (Note: To successfully filter, the search term must contain at least 3 characters) Eg: https://api.tourwriter.com/suppliers/?search=hilton |
Example:
GET https://api.tourwriter.com/suppliers
Response:
[
{
"id": 1255,
"name": "Sheraton On The Park"
},
{
"id": 1256,
"name": "Pullman Reef Hotel Casino"
},
{
"id": 1257,
"name": "Barrier Reef Cruises"
}
]
GET Suppliers (Detailed)
Use this method to retrieve one or more suppliers
Url: https://api.tourwriter.com/suppliers/{supplier id}
ID | Id: {supplier id} Eg: https://api.tourwriter.com/suppliers/1255 or Ids with a comma delimited string: {supplier id},{supplier id},{supplier id}... Eg: https://api.tourwriter.com/suppliers/1255,1525,3525 |
Optional parameters
includeServices | To include services (boolean) Eg: https://api.tourwriter.com/suppliers/1255?includeServices=True |
includeOptions | To include options (boolean) Eg: https://api.tourwriter.com/suppliers/1255?includeOptions=True |
includeAllocations | To include allocations (boolean) Eg: https://api.tourwriter.com/suppliers/1255?includeAllocations=True |
ratesFrom | To filter rates based on from date (yyyy-mm-dd) Eg: https://api.tourwriter.com/suppliers/1255?ratesFrom=2019-09-10 |
ratesTo | To filter rates based on To date (yyyy-mm-dd) Eg: https://api.tourwriter.com/suppliers/1255?ratesTo=2019-09-10 |
search | To filter based on search term. (Note: To successfully filter, the search term must contain at least 3 characters) Eg: https://api.tourwriter.com/suppliers/1255?search=hilton |
Example
Response:
[
{
"id": 1275,
"name": "Park Hotel",
"host": null,
"street": "ABC Road,",
"city": "City Centre",
"region": "Wellington",
"state": "Wellington",
"country": "New Zealand",
"postcode": null,
"latitude": "-3.8557545669922",
"longitude": "51.209374885938",
"phone": "01 123456789",
"mobilePhone": null,
"freePhone": null,
"fax": "01 123456789",
"email": "abc@park.com",
"website": "www.park123.com",
"postAddress": null,
"comments": null,
"description": "Park combines the traditional values of courtesy, care and comfort with Park’s discreet residential and sophisticated style. Whether your visit to the hotel is for an important meeting or a relaxing weekend away, Park offers a wide range of guest services that will make your stay memorable.",
"grade1": "",
"grade2": "",
"refunds": null,
"active": true,
"updatedOn": null,
"services": [
{
"id": 2934,
"name": "City Harbour King",
"type": "Accommodation",
"currency": "NZD",
"active": true,
"deleted": null,
"allocations": [
],
"options": [
{
"id": 22829,
"name": "Double",
"deleted": null,
"price": 890,
"net": 732,
"validFrom": "2018-04-01",
"validTo": "2019-03-31",
"optionTypeId": 5,
"optionTypeName": "Adult"
}
]
},
{
"id": 2936,
"name": "City Harbour Deluxe",
"type": "Accommodation",
"currency": "NZD",
"deleted": null,
"allocations": [
],
"options": [
{
"id": 22803,
"name": "Double",
"deleted": null,
"price": 1040,
"net": 952,
"validFrom": "2018-04-01",
"validTo": "2019-03-31",
"optionTypeId": 5,
"optionTypeName": "Adult"
}
]
}
]
}
]
Itineraries
Overview
URL | https://api.tourwriter.com/itineraries |
Methods supported | GET, POST, PUT |
Description | Retrieve itineraries |
Content-type | application/json |
GET Itineraries (Summarized)
Use this method to retrieve all itineraries with id and name
Url: https://api.tourwriter.com/itineraries
Example:
GET https://api.tourwriter.com/itineraries
Response:
[
{
"id": 991,
"name": "FIT DUAL COUNTRY BOOKING "
},
{
"id": 992,
"name": "FIT SELF DRIVE BOOKING"
},
{
"id": 993,
"name": "GROUP BOOKING - Southern Panorama - Apr 2016"
}
]
GET Itineraries (Detailed)
Use this method to retrieve one or more Itineraries
Url: https://api.tourwriter.com/itineraries/{itinerary id}
For Updates please refer to <add jump link>
Required parameter
id | Id: {itinerary id} Eg: https://api.tourwriter.com/itineraries/994 or Ids with a comma delimited string: {itinerary id},{itinerary id},{itinerary id}... Eg: https://api.tourwriter.com/itineraries/994,995,996 |
Optional parameters
includeItems | To include booking items (boolean) Eg: https://api.tourwriter.com/itineraries/994?includeItems=True |
includeTasks | To include tasks (boolean) Eg: https://api.tourwriter.com/itineraries/994?includeTasks=True |
includePassengers | To include passengers (boolean) Eg: https://api.tourwriter.com/itineraries/994?includePassengers=True |
includeAgent | To include agent (boolean) Eg: https://api.tourwriter.com/itineraries/994?includeAgent=True |
includeNulls | To include nulls (boolean) Eg: https://api.tourwriter.com/itineraries/994?includeNulls=True |
types | To filter by itinerary type name. Accepts comma separated string Eg: https://api.tourwriter.com/itineraries/994?types=package,addon |
updatedAfter | To filter by itinerary updated value Eg: https://api.tourwriter.com/itineraries/994?updatedAfter=2019-12-01 |
[
{
"id": 1956,
"code": "ADF324",
"packageId": 995,
"name": "Test Itinerary Name",
"active": true,
"displayName": "Itinerary Display Name1",
"startDate": "2018-02-01T00:00:00",
"endDate": "2018-02-01T00:00:00",
"assignedTo": "admin",
"status": "Quotation",
"source": "Web Site",
"type": "Sale",
"comments": "Itinerary comments go here",
"totalPrice": 2990,
"totalPaid": 897,
"currency": "NZD"
}
]
Example
Response:
[
{
"id": 995,
"code": "",
"packageId": null,
"name": "McKinstry, Frederick & Florence",
"active": true,
"displayName": "Frederick and Florence McKinstry",
"startDate": "2017-01-15T09:15:00",
"startCity": "Christchurch",
"startFlight": "NZ 0513 15 JAN AKL CHC 0755 0915",
"startNote": "International Flight\r\nNZ0007 13 JAN SFO AKL 1945 0555 +2",
"endDate": "2017-01-28T00:00:00",
"endCity": "Sydney Airport (Kingsford Smith Airport)",
"endFlight": "NZ 0104 25 JAN SYD AKL 1145 1450",
"endNote": "Connecting Flight\r\nNZ0008 25 JAN AKL SFO 0730 1055 (25 JAN)",
"assignedTo": "admin",
"department": "Inbound FIT",
"branch": null,
"status": "Confirmed - Awaiting Deposit",
"source": "Referral",
"type": null,
"comments": "This itinerary works with the New Quotation Template 1\r\n\r\nClient is booking the flights from SFO to CHC and from SYD to SFO (as per the details above)\r\n\r\nBased on a Self drive itinerary request.",
"totalPrice": 107462.41,
"totalPaid": 0,
"currency": "CNY",
"updatedOn": "2017-06-14T11:12:01.053",
"folderName": "Itinerary Report 1",
"items": [
{
"id": 1205,
"bookingId": 1797,
"name": "Christchurch to Wanaka, Driving Christchurch to Wanaka",
"supplier": "New Zealand Locations - Master",
"startDate": "2017-01-17",
"startTime": null,
"endDate": null,
"endTime": null,
"quantity": null,
"numberOfDays": null,
"optionId": 19999,
"type": "Directions",
"configuration": null,
"status": null,
"reference": null,
"voucherNote": null,
"supplierNote": null,
"passengerNote": null,
"publishingNote": null,
"price": 0,
"net": 0,
"netCurrency": "USD",
"invoiced": false
},
{
"id": 1199,
"bookingId": 1792,
"name": "Junior Lakeview Suite, Double",
"supplier": "Sofitel Queenstown",
"startDate": "2017-01-20",
"startTime": "14:00",
"endDate": "2017-01-23",
"endTime": "10:00",
"quantity": 1,
"numberOfDays": null,
"optionId": 20894,
"type": "Accommodation",
"configuration": "Double",
"status": null,
"reference": null,
"voucherNote": null,
"supplierNote": null,
"passengerNote": "We have requested early checkin of 10.00am 造字 造字 造字 造字 造字 造字 Queenstown, 造字 造字 造字 ....",
"publishingNote": null,
"price": 3267.94,
"net": 600,
"netCurrency": "NZD",
"invoiced": false
}
],
"passengers": [
{
"id": 1794,
"displayName": "Frank McKinstry",
"firstName": "Frank",
"lastName": "McKinstry",
"title": "Master",
"birthDate": null,
"sex": null,
"street": null,
"city": null,
"state": null,
"country": null,
"postCode": null,
"email": null,
"phone": null,
"workPhone": null,
"note1": null,
"note2": null,
"note3": null,
"note4": null,
"note5": null,
"note6": null,
"note7": null,
"note8": null,
"updatedOn": "2015-06-26T16:25:28.817",
"roomType": null,
"roomNumber": null
},
{
"id": 1795,
"displayName": "Amy McKinstry",
"firstName": "Amy",
"lastName": "McKinstry",
"title": "Miss",
"birthDate": null,
"sex": null,
"street": null,
"city": null,
"state": null,
"country": null,
"postCode": null,
"email": null,
"phone": null,
"workPhone": null,
"note1": null,
"note2": null,
"note3": null,
"note4": null,
"note5": null,
"note6": null,
"note7": null,
"note8": null,
"updatedOn": "2015-06-26T16:25:39.417",
"roomType": null,
"roomNumber": null
}
],
"configurations": null,
"agent": [
{
"id": 2,
"name": "Demonstration Agent ??",
"email": null,
"phone": null,
"contactId": null,
"contactName": null,
"contactFirstName": null,
"contactLastName": null,
"contactEmail": null,
"contactPhone": null
}
],
"tasks": [
{
"id": 280,
"name": "01 Follow Up Quote",
"dueOn": "2017-06-23T00:00:00",
"completedOn": "2017-06-09T15:19:57.047",
"note": null
},
{
"id": 281,
"name": "02 Collect Deposit",
"dueOn": "2017-06-30T00:00:00",
"completedOn": "2017-06-09T15:19:54.6",
"note": null
},
{
"id": 282,
"name": "03 Request Supplier Confirmations",
"dueOn": null,
"completedOn": "2017-06-14T10:39:31.86",
"note": null
},
{
"id": 283,
"name": "04 Confirm Final Payment",
"dueOn": null,
"completedOn": null,
"note": null
},
{
"id": 284,
"name": "05 Send Final Itinerary",
"dueOn": null,
"completedOn": null,
"note": null
},
{
"id": 285,
"name": "06 Send Trip Follow Up",
"dueOn": null,
"completedOn": null,
"note": null
}
]
}
]
POST Itineraries
Use this method to create an itinerary
Url: https://api.tourwriter.com/itineraries
POST DATA
packageId | Template itinerary id (i.e. existing itinerary id in Tourwriter database) that you want to create a new itinerary from. This will copy all the data from source itinerary. Note: the values of other elements can be overridden. Alternatively, set the value to null to create the blank itinerary and populate the data |
code | Custom Code field in itinerary tab |
name | Itinerary name field in itinerary tab |
displayName | Display name field in itinerary tab |
startDate | Itinerary start date field in itinerary tab |
startCity | Itinerary start city field in itinerary tab |
startFlight | Itinerary start flight field in itinerary tab |
startNote | Itinerary start note field in itinerary tab |
endDate | Itinerary end date field in itinerary tab |
endCity | Itinerary end city field in itinerary tab |
endFlight | Itinerary end flight field in itinerary tab |
endNote | Itinerary end note field in itinerary tab |
agent | Agent name field in itinerary tab Note: Setting to null value will set the agent to default agent name |
assignedTo | Assigned to field in itinerary tab |
department | Department name field in itinerary tab |
branch | Branch name field in itinerary tab |
status | Itinerary status field in itinerary tab |
source | Itinerary source field in itinerary tab |
type | Itinerary type field in itinerary tab |
comments | Itinerary comments field in itinerary tab |
totalPrice | Use this field to override itinerary final price. |
totalPaid | Use this field to add payments into clients > payment tab. Note: at least 1 passenger is required in passengers collection |
currency | Itinerary currency |
folderName | Use this field to store the newly created itinerary in the named folder. If the folder name does not exist, itinerary will be created in the root folder |
Elements of Items
There are two ways you can use the items collection
When packageId = null
- items [] – No bookings will be created
- items[{Items collection POST data}] – bookings will be added as per the items collection POST data
When packageId = {template itinerary id}
- items [] – All bookings will be copied from the source itinerary id
- items[{Items collection POST data}] – All bookings will be copied from the source itinerary id + bookings will be added as per the items collection POST data
id | Use this field to create a copy of booking from another itinerary. Usage: id from items collection of another itinerary that you need to copy from Alternatively, the field can be set to null if you want to create a booking directly from supplier (see optionId) Note: The other elements in Items collection can be changed to new values |
name | Item description field in bookings tab Usage of elements id or optionId will auto populate this field. However, this field can overridden |
supplier | Booking name field in bookings tab Usage of elements id or optionId will auto populate this field. However, this field can overridden |
startDate | Booking start date |
startTime | Booking start time |
endDate | Booking end date |
endTime | Booking end time |
quantity | Booking quantity |
numberOfDays | Booking number of days |
optionId | Use this field to create booking from the suppliers loaded in Tourwriter. The optionId can be found in Options collection of Suppliers GET method or Items collection of Itineraries GET method. Alternatively, the field can be set to null if you want to create a copy of booking from another itinerary (see id above) Note: The other elements in Items collection can be changed to new values |
status | Booking status field in bookings tab Note: the status values should exist in your database |
reference | Booking reference field in bookings tab |
voucherNote | Voucher note field in bookings tab |
supplierNote | Supplier note field in bookings tab |
passengerNote | Publishing 1 field in bookings tab |
price | Gross unit price (Note: The field expects Gross unit price in the POST/PUT itineraries method. However, the price returned in GET is Gross Final price. Click here to learn how to convert the Final to Unit values) |
net | Net unit price (Note: The field expects Net unit price in the POST/PUT itineraries method. However, the price returned in GET is Net Final price. Click here to learn how to convert the Final to Unit values) |
Elements of passengers
displayName | Display name field in Contacts |
firstName | First name field in Contacts |
lastName | Last name field in Contacts |
title | Title field in Contacts |
birthDate | Birth date field in Contacts Date format: YYYY-MM-dd |
sex | Sex field in Contacts |
street | Street field in Contacts |
state | State name field in Contacts |
city | City name field in Contacts |
postCode | Postcode field in Contacts |
country | Country name field in Contacts |
Email1 field in Contacts | |
phone | Home phone field in Contacts |
workPhone | Work phone field in Contacts |
note1 | Note1 field in Contacts > Additional tab |
note2 | Note2 field in Contacts > Additional tab |
note3 | Note3 field in Contacts > Additional tab |
note4 | Note4 field in Contacts > Additional tab |
note5 | Note5 field in Contacts > Additional tab |
note6 | Note6 field in Contacts > Additional tab |
note7 | Note7 field in Contacts > Additional tab |
note8 | Note8 field in Contacts > Additional tab |
roomType | Room type of the passenger(Eg:Double,Single etc.) |
Example
POST https://api.tourwriter.com/itineraries
Example POST data:
{
"packageId": null,
"code": "ADF324",
"name": "Test Itinerary",
"displayName": "Itinerary Display Name1",
"startDate": "2018-02-01",
"startCity": null,
"startFlight": null,
"startNote": null,
"endDate": "2018-02-01",
"endCity": null,
"endFlight": null,
"endNote": null,
"agent": null,
"assignedTo": "admin",
"department": null,
"branch": null,
"status": "Quotation",
"source": "Web Site",
"type": "Sale",
"comments": "Itinerary comments go here",
"totalPrice": null,
"totalPaid": null,
"currency": "NZD",
"folderName": "Templates 12",
"items": [{
"id": 1200,
"name": "Really Nice Room, Double",
"supplier": "Pullman Auckland",
"startDate": "2018/02/01",
"startTime": "15:00",
"endDate": null,
"endTime": null,
"quantity": 1,
"numberOfDays": 2,
"optionId": null,
"status": "Confirmed",
"reference": "JKASDFHA",
"voucherNote": "Notes for Voucher",
"supplierNote": "Notes for Supplier",
"passengerNote": "Notes for Passengers",
"price": 300.00,
"net": 240.00
},{
"id": null,
"name": "Best of Both Worlds, Adult",
"supplier": "Bush and Beach",
"startDate": "2018/02/01",
"startTime": "18:00",
"endDate": null,
"endTime": null,
"quantity": 1,
"numberOfDays": 2,
"optionId": 23888,
"status": "Confirmed",
"reference": "JKASDFHA",
"voucherNote": null,
"supplierNote": null,
"passengerNote": null,
"price": 199.00,
"net": 159.20
}],
"passengers": [{
"displayName": "John Smith",
"firstName": "John",
"lastName": "Smith",
"title": "Mr.",
"birthDate": "2000/12/01",
"sex": "Male",
"street": "address of John",
"state": "Strandon ",
"city": "New Plymouth ",
"postCode": "4312",
"country": "New Zealand",
"email": "johnsmith@123.com",
"phone": "+64-01234567899",
"workPhone": "+64-123456789",
"note1": "Note 1",
"note2": "Note 2",
"note3": "Note 3",
"note4": "Note 4",
"note5": "Note 5",
"note6": "Note 6",
"note7": "Note 7",
"note8": "Note 8",
"roomType": "Double"
},{
"displayName": "Jane Smith",
"firstName": "Jane",
"lastName": "Smith",
"title": "Mrs.",
"birthDate": "2000/12/01",
"sex": "Female",
"street": "address of Jane",
"state": "Strandon ",
"city": "New Plymouth ",
"postCode": "4312",
"country": "New Zealand",
"email": "janesmith@123.com",
"phone": "+64-01234567899",
"roomType": "Double"
}
]
}
Example Response after successful POST:
{
"id": 1021,
"code": "ADF324",
"name": "Test Itinerary",
"active": true,
"displayName": "Itinerary Display Name1",
"startDate": "2018-02-01T00:00:00",
"endDate": "2018-02-01T00:00:00",
"assignedTo": "admin",
"status": "Quotation",
"source": "Web Site",
"comments": "Itinerary comments go here",
"totalPrice": 1868.59,
"totalPaid": 0.00,
"currency": "NZD",
"updatedOn": "2019-12-12T00:19:42.74"
}
PUT Itineraries
Use this method to update an itinerary
Url: https://api.tourwriter.com/itineraries/{itinerary id}
DATA for PUT method
Same as Itinerary POST data but with the below changes
- All the fields are needed related to itinerary. If any fields are omitted in the POST data, it will be considered as null and the previous value will be set to null. However, items, passengers and tasks collection can be omitted if there are no changes needed. Alternatively, these collections may be added as empty collection. Eg: Items[], Passengers[], tasks[].
- Both the POST and PUT methods expect price and net fields to be Net Unit and Gross Unit values respectively. The values returned from the GET method are Gross Final and Net Final values. To convert the Final to Unit values from the GET method, use the below formula:
- Net unit = Net Final / (Qty x NumberofDays)
- Gross unit = Gross Final / (Qty x NumberOfDays)
- packageId is ignored.
- In Items collection, bookingId is needed for updating the booking. The bookingId can be fetched using GET Itineraries (Detailed). If bookingId is set to null, new bookings can be added as per the items collection explained in Itineraries POST method.
- Additional tasks collection is available in PUT method. (see below table).
id | Id field is required. This field can be fetched from GET itineraries (Detailed) |
name | Task name field in Task grid |
dueOn | Date due field in Task grid Date format: YYYY-MM-DD |
completedOn | Date completed field in Task grid Date format: YYYY-MM-DD |
note | Note field in Task grid |
Example
PUT https://api.tourwriter.com/itineraries/1020
Example POST data for PUT method:
{
"code": "ADF324",
"name": "Test Itinerary edited",
"displayName": "Itinerary Display Name1",
"startDate": "2018-02-01",
"startCity": null,
"startFlight": null,
"startNote": null,
"endDate": "2018-02-01",
"endCity": null,
"endFlight": null,
"endNote": null,
"agent": null,
"assignedTo": "admin",
"department": null,
"branch": null,
"status": "Quotation",
"source": "Web Site",
"type": "Sale",
"comments": "Itinerary comments go here",
"totalPrice": null,
"totalPaid": null,
"currency": "NZD",
"folderName": "Templates 12",
"items": [{
"id": 1200,
"name": "Really Nice Room, Double",
"supplier": "Pullman Auckland",
"startDate": "2018/02/01",
"startTime": "15:00",
"endDate": null,
"endTime": null,
"quantity": 1,
"numberOfDays": 2,
"optionId": null,
"status": "Confirmed",
"reference": "JKASDFHA",
"voucherNote": "Notes for Voucher",
"supplierNote": "Notes for Supplier",
"passengerNote": "Notes for Passengers",
"price": 300.00,
"net": 240.00
},{
"id": null,
"name": "Best of Both Worlds, Adult",
"supplier": "Bush and Beach",
"startDate": "2018/02/01",
"startTime": "18:00",
"endDate": null,
"endTime": null,
"quantity": 1,
"numberOfDays": 2,
"optionId": 23888,
"status": "Confirmed",
"reference": "JKASDFHA",
"voucherNote": null,
"supplierNote": null,
"passengerNote": null,
"price": 199.00,
"net": 159.20
}],
"passengers": [{
"displayName": "John Smith",
"firstName": "John",
"lastName": "Smith",
"title": "Mr.",
"birthDate": "2000/12/01",
"sex": "Male",
"street": "address of John",
"state": "Strandon ",
"city": "New Plymouth ",
"postCode": "4312",
"country": "New Zealand",
"email": "johnsmith@123.com",
"phone": "+64-01234567899",
"workPhone": "+64-123456789",
"note1": "Note 1",
"note2": "Note 2",
"note3": "Note 3",
"note4": "Note 4",
"note5": "Note 5",
"note6": "Note 6",
"note7": "Note 7",
"note8": "Note 8",
"roomType": "Double"
},{
"displayName": "Jane Smith",
"firstName": "Jane",
"lastName": "Smith",
"title": "Mrs.",
"birthDate": "2000/12/01",
"sex": "Female",
"street": "address of Jane",
"state": "Strandon ",
"city": "New Plymouth ",
"postCode": "4312",
"country": "New Zealand",
"email": "janesmith@123.com",
"phone": "+64-01234567899",
"roomType": "Double"
}
]
}
Example Response after successful POST:
[
{
"id": 1020,
"code": "ADF324",
"name": "Test Itinerary edited",
"active": true,
"displayName": "Itinerary Display Name1",
"startDate": "2018-02-01T00:00:00",
"endDate": "2018-02-01T00:00:00",
"assignedTo": "admin",
"status": "Quotation",
"source": "Web Site",
"comments": "Itinerary comments go here",
"totalPrice": 3737.18,
"totalPaid": 0.00,
"currency": "NZD",
"updatedOn": "2019-12-12T06:06:47.463"
}
]