NAV Navbar
Ingresso logo
cURL Python Javascript

Introduction

The Ingresso API is designed to allow you to sell from Ingresso’s inventory of event tickets. Ingresso has connected to a large number of ticketing system APIs, allowing us to transact directly on the venue’s system. By integrating with the Ingresso API you are able to view and purchase live ticketing inventory from a number of different venues.

Example partners that have integrated with the Ingresso API are GetYourGuide and lastminute.com. We also build our own ticketing websites entirely on top of the API, for example From The Box Office.

The Ingresso API is a fully transactional API, loosely based on REST. You format GET or POST requests in JSON and you will receive either a JSON-formatted response or an HTTP error. The API is internally known as F13, which is why you see /f13 in the endpoints.

We describe objects in a consistent way across different resources (for example the output of events and performances includes a cost_range object and this is described in the same format). The idea behind this is that standard code can be used on the client side to read all parts of the output.

This API replaces the Ingresso XML API. The XML API relies on temporary tokens from each call being passed in to the next call; these has been removed in favour of permanent IDs. One benefit of this change is that a call near the end of the booking process, such as reserve, can be called without needing to remake the preceding calls (such as requesting availability), opening up additional potential solutions. The output is also more compact leading to faster response times in most cases.

Postman examples

Postman screenshot

We have a public library available for Postman that closely matches the examples included in this documentation.

Click below to import our collection of API examples.

Run in Postman or download directly here

F13 API Browser

F13 API Browser

We have also developed the F13 API Browser.

Basic booking flow

The Ingresso API was designed to support the more complex task of booking tickets for live entertainment events, and some parameters use language (e.g. seat) reflective of that. However, the API includes support for booking a wide range of different products, including general-admission attractions products, merchandise and more.

For most products that have limited capacity availability, the following basic booking flow should be followed to ensure the most accurate availability is shown to your customer, but some additional parameters may be used to shortcut this flow for some types of products.

List events including from prices and a single image

curl https://api.ticketswitch.com/f13/events.v1 \
    -u "demo:demopass" \
    -d "req_cost_range" \
    -d "req_media_triplet_one" \
    --compressed \
    -G
gzip must be used for all requests (with curl you can use the –compressed flag). Most http libraries support compression (though you may need to enable this somehow), but if not and you are receiving gzip errors you can pass “Accept-Encoding: gzip” in the headers then unzip the response. curl uses the -u flag to pass HTTP Basic Authentication credentials in the format user:password.

List performances for event ID 6IF

curl https://api.ticketswitch.com/f13/performances.v1 \
    -u "demo:demopass" \
    -d "event_id=6IF" \
    -d "page_len=200" \
    --compressed \
    -G

Display availability for the 9th May performance

curl https://api.ticketswitch.com/f13/availability.v1 \
    -u "demo:demopass" \
    -d "perf_id=6IF-B0T" \
    --compressed \
    -G

Reserve 2 tickets in price band A in the Circle

curl https://api.ticketswitch.com/f13/reserve.v1 \
    -u "demo:demopass" \
    -d "perf_id=6IF-B0T" \
    -d "ticket_type_code=CIRCLE" \
    -d "price_band_code=A/pool" \
    -d "no_of_seats=2" \
    --compressed \
    -G

Purchase the tickets

curl https://api.ticketswitch.com/f13/purchase.v1 \
    -u "demo:demopass" \
    -d "transaction_uuid=XXXXXXXX" \
    --compressed \
    -G

The Ingresso API supports multiple use cases and variations, but below is a typical workflow:

Philosophy

Types of API integration

The Ingresso API supports a variety of different integration types.

  1. Full integration: this is where our partner uses all functionality of the Ingresso API to retrieve listings of events and performances (often in advance to populate their own database) then to request availability and reserve and purchase tickets in real-time.

  2. Feather: Ingresso offer a seat selection widget product called Feather that can be embedded on your website. It is used in conjunction with the Ingresso API to reduce the development needed to offer seat selection to your customers. You use the API to retrieve performances so you can present a calendar to customers. When a performance is selected, you use Feather to display availability for that performance, and to reserve the customer’s chosen seats. Feather will handle complexities like preventing single seats from being left, and suggesting alternate seats when the desired seats are no longer available. If the reserve is successful you will return a transaction reference that you can then purchase via the API. View the Feather documentation and demo.

  3. Partial Integration: Ingresso also offer partners an individually branded “white label” ticketing website - for example Ticketmaster Theatre and From The Box Office are fully developed by Ingresso. It is possible to use the API in conjunction with a white label website as a partial integration. Some examples of partial integrations:

    a) Maintain a listing of events on your own site, and use Ingresso’s white label website for booking the tickets. In this case the Ingresso API can be used to list events.

    b) Ingresso have invested in a high-conversion booking app (where the customer selects their performance and seats). This page is often where most development time is spent. It is possible to link to our booking page and we will automatically redirect back to your checkout page once the customer has successfully reserved their seats. You can link to our full booking page or just use Feather to add seat selection to your site.

    c) Use the Ingresso API to display events, performances and availability, then send your customer to our white label website for checkout. It is possible for Ingresso to then redirect the customer back to your confirmation page if the purchase is successful.

Payment Options

If you use the checkout page of Ingresso’s white label website, then Ingresso will take care of collecting payment from the customer. However if you wish to develop your own checkout page these are the options for taking payment:

  1. You take payment: you purchase tickets from Ingresso on credit / on account and take payment from the customer yourself. You will be invoiced regularly by Ingresso. This option is typically only offered to partners with the capability to sell a high volume of tickets. There are two ways for you to take payment:

    a) Using a payment provider of your choosing.

    b) Using your own Stripe account. Stripe is a developer-friendly payment provider that is simple to integrate with. Our API provides integration support for Stripe. You just need to collect a Stripe token after your customer enters their payment details; Ingresso’s Stripe integration will then ensure the payment is captured and all edge cases are handled.

  2. Ingresso takes payment: for the majority of partners Ingresso will take payment using Stripe, so you need to collect a Stripe token and pass that in when purchasing tickets.

These options are discussed in more detail in purchase.

How to get access to the API

All examples shown in this documentation are for the demo user. This user has access to test product only - you can make purchases with this user without any impact on live tickets, or any need to contact us first.

The process for going on sale is:

  1. Start your integration using the demo user. This is the user that all partners use during testing

  2. Once you have made good progress contact us to agree a commission deal: commercial@ingresso.co.uk

  3. When you have finished the integration we will check to ensure you support the required functionality

  4. We will then give you a live account and you can go live

Authentication

Example request with authentication

curl https://api.ticketswitch.com/f13/events.v1 \
    -u "demo:demopass" \
    -d "s_keys=matthew" \
    -d "s_coco=uk" \
    --compressed \
    -G
from pyticketswitch import Client

client = Client(user='demo', password='demopass')
curl uses the -u flag to pass basic auth credentials in the format user:password.

Connect as the demosub subuser with Dutch as the preferred language

curl https://api.ticketswitch.com/f13/events.v1/demo/demosub/nl \
    -u "demo:demopass" \
    -d "s_keys=matthew" \
    -d "req_extra_info" \
    --compressed \
    -G

Authenticate when using the API by including your username and password in the request. Authentication to the API is performed via HTTP Basic Auth.

This is all you need, but there are two additional optional parameters that can be included:

  1. Some of our partners require sub users for particular use cases such as running their own affiliate programme.

  2. It is possible to pass in a preferred language code, overriding the language code/s in the HTTP header.

These parameters are included in the URL after the version number:

/f13/events.v1/USER/SUBUSER/LANG_CODE

Using a ‘-’ for the subuser or language code will cause it to be ignored, so to ignore the subuser:

/f13/events.v1/USER/-/LANG_CODE

Errors

Example

HTTP/1.1 400 Bad Request

{
  "error_code": 8,
  "error_desc": "Bad data supplied"
}
APIError(
    msg='Bad data supplied',
    code=8,
    response=<Response [400]>
)

When an error happens the API will return a non 2XX HTTP status code and a message about the error in the response body. The message will include a human readable description of the error and a code that can be used by application to recognise the issue and handle it appropriately.

Some method calls can have partial failures. For example a reservation call might be successful for one order in the trolley but fail to reserve a second order, or a purchase call might be successful in that we successfully attempted a payment but the users card was declined, or the backend system fell over mid transaction. In these situations the API will return a 200 HTTP status code with details of the issues in the response body. You should consult the documentation for the specific end point for details on how to handle these situations.

Status codes

Details of the general HTTP status codes can be found below:

Status Code Description
200 - OK The response can be interpreted as explained in the documentation.
400 - Bad Request Your call was missing data required to satisfy the request. This response generally occurs due to missing parameters.
401 - Unauthorised No authentication parameters were provided or the given parameters were invalid.
403 - Forbidden You are trying to access something your account doesn’t have access to.
404 - Not Found Then the endpoint you were trying to reach does not exist.
405 - Method Not Allowed You have tried to use a POST request when the endpoint was expecting a GET request (or vice versa).
410 - Gone The resource you were trying to access no longer exists. This is primarily used around transactions when temporary resources (such as callouts) have expired.
460 - Invalid Parameters The parameters passed to the API were technically valid, but were rejected due to their content. Refer to the error description and error code for further details.
5XX - Server Errors Something unexpectedly went wrong and the API was unable to do what you asked it to do. Refer to the error description and error code for further details.

One specific case that is worth mentioning in detail is when the API returns a 502 HTTP status code. This indicates that your request required a connection to an upstream server (for example the supplier ticketing system, or a payment provider), but we were unable to establish the connection. Some of the supplier systems that our API connects to are fragile; we do what we can to mitigate this, but sometimes those upstream servers simply won’t be available to service your request. In these situations you could attempt to retry the request in case it was just momentary issue, failing that waiting a short time may help. Both scheduled and unscheduled major outages will be recorded on our status page.

Error codes

Error codes provide a computer readable classifier of an error. They will be useful in identifying errors and handling them appropriately.

Error Code Description
2 Bad channel.
3 User authentication failure.
4 Failed to create connection to the backend system.
5 Host is on a forbidden network.
6 Failed to connect to database.
7 Membership authentication failed.
8 Bad data supplied.
2000 Email address is invalid. This error will also provide a secondary error_key field that will provide a code for working out exactly what’s wrong with the email address (see below).
3000 Unrecognised card type from number.
3001 Card type not accepted.
3002 Not a valid card number.
3003 Invalid expiry date.
3004 Invalid CV2.
3005 Missing issue number.
3006 Invalid issue number.
3007 Missing start date.
3008 Invalid start date.

Email error keys

Email error keys break down the 2000 error code into more explicit issues.

Key Description
addr_dot_before_at_must_be_quoted A ‘.’ before the ‘@’ sign should be quoted
addr_cannot_end_in_dot Address cannot end in ‘.’
addr_cannot_have_dot_immediately_after_at Cannot have ‘.’ immediately after ‘@’ sign
addr_cannot_have_dot_dot_after_at Cannot have ‘..’ after ‘@’ sign
addr_cr_within_quotes Carriage return within quotes
addr_cr_not_allowed_after_at Carriage returns not allowed after ‘@’ sign
addr_may_not_be_blank Email addresses may not be blank
addr_may_not_end_with_at Email addresses may not end with ‘@’ sign
addr_may_not_start_with_at Email addresses may not start with ‘@’ sign
addr_missing_at Missing ‘@’ sign
addr_needs_at_least_one_dot Must have at least one ‘.’ after ‘@’ sign
addr_spaces_before_at_must_be_quoted Spaces before ‘@’ sign must be quoted
addr_spaces_not_allowed_after_at Spaces not allowed after ‘@’ sign
addr_tabs_not_allowed_after_at Tabs not allowed after ‘@’ sign
addr_unterminated_quote_before_at Unterminated quote before ‘@’
addr_non_ascii_in_quotes Non-ASCII character in quotes
addr_dot_expected_after_quotes A ‘.’ is expected after quotes
addr_non_ascii_before_at Non-ASCII character before ‘@’ sign
addr_control_character_before_at Control character before ‘@’ sign
addr_specials_before_at_must_be_quoted Special characters before ‘@’ sign must be quoted
addr_non_ascii_after_at Non-ASCII character after ‘@’ sign
addr_control_character_after_at Control character after ‘@’ sign
addr_specials_after_at Special characters not allowed after ‘@’ sign
addr_bad_email_domain This domain is not e-mailable

Backend system errors

It’s important to note that the majority of errors that you are likely to see are caused by failures in the backend systems that we are attempting to connect to your behalf. Generally these issues will present themselves in the availability, reservation, and purchase calls. If you experience unexpected results from these calls but there is no indication of an explicit error having happened it’s worth checking our status page to see if there are any known issues ongoing with any of the backend systems:

https://status.ingresso.co.uk/

Variables controlling output

The output from a given resource may be augmented beyond the basic result in one of two ways. Firstly there are extra functions which may be available for a given resource, which are specific to that resource. These are triggered using variables with the prefix add_ such as add_discount_codes on the availability resource which is used to control whether or not discount codes are also retrieved and returned.

The second type of augmentation is specific to the returned objects themselves and is thus applicable to the output of any resource which returns one of these objects. The most obvious example is an event object, which can be described with many extra pieces of information about it. These variables are all prefixed with req_ as they are requests to the objects to output something extra or different about themselves, for example req_cost_range.

Note that the req_ and add_ variables all result in extra processing to retrieve the requested data, which will slow down the resource, sometimes substantially. They should therefore only be used where necessary.

Request ID logging

In order to more easily trace the effect of API calls through the TicketSwitch system, every API response will include a tracking ID in the header X-Request-Id. This value is used internally to the Ingresso platform to track requests to supplier systems and other internal services, and is recorded against reservation and purchase records as well as call logs. If you need to debug any request made to the API, please include this request ID when contacting Ingresso. We recommend including this and other headers in your logs if an error occurs.

API libraries / SDKs

Our API libraries implement a thin client over the API. Where the API will return JSON, the API wrappers return language-specific objects (at the moment we have only implemented a single language):

Examples will be included in this documentation, but if you require further detail you can refer to the appropriate documentation for the language wrapper.

Required Minimum Functionality

Before your application can go live, there are a number of minimum implementation requirements it must meet. The test data available can help make sure your implementation is working as expected and can handle various types of errors and edge cases. To validate the functionality of your application, Ingresso will use the following representative tests.

List performance dates or times

A given event may have multiple performances on different days and times, and the customer must be able to choose the one they want to attend. This can be done by listing them, or in a calendar interface, or in any other way that is appropriate for your application.

Representative Test: User selects The Unremarkable Incident of the Cat at Lunchtime (event ID 7AB)
When the event is selected in the interface,
Then it should display the two available performances, 1 January {this year + 1} and 1 January {this year + 2}, at 15:30:00 UTC.

Support undated events

Some venues such as theme parks sell undated tickets. These events have need_performance = false and have an auto-generated performance that your integration should auto-select. It should be possible for customers to purchase tickets without having to choose or see the auto-generated date in the API.

Representative Test: User selects Ingressoland - Any Time (event ID 1D7B8)
It is possible to make it to checkout without needing to select a date (i.e. the performance is auto-selected).

Support best available booking flow

At a minimum, the customer must be able to specify the number of tickets they want and for which ticket type and price band. The Ingresso backend will then reserve the best available tickets that meet the requirements.

Representative Test: User selects 3 tickets for event 6IF in the stalls band B
When the reservation is made
Then the application shows a reservation confirmation screen with 3 tickets from that price band, and allows the user to proceed with the booking and payment process

Display the full ticket price to the customer before purchase

The customer must be shown the full price they will pay before the purchase is confirmed and their payment taken.

Representative Test: User confirms reservation of 1 ticket for event 7AB in the stalls band A (e.g. seat B4)
When the confirmation and payment screen is displayed
Then the full price should be displayed as £55.00, showing a £50.00 seat price and a £5.00 surcharge. Any dispatch methods that incur an additional cost should also be listed separately. A total price should be displayed in a highlighted font showing the price the customer will pay (by adding the prices together).

Display different send methods including eTickets

Various venues support different methods of sending tickets (including post, collect from box office, or printable eTickets). Some of these may carry an additional fee. Where available, different send methods should be offered to the customer, and your application should support eTickets (either provided by Ingresso or your own format with a barcode retrieved from the Ingresso API).

Representative Test: User confirms reservation of tickets for Toy Story – The Opera (7AA)
When the customer selects the Toy Story(7AA) event
Then the available send methods of Printable eTicket and Post worldwide are shown.

Representative Test: User selects Printable eTicket and checks out
When the customer has purchased the tickets
Then the ticket with the appropriate barcode will be sent to their email or otherwise permanently saved within your application after purchase has been confirmed

Display special seat conditions to customer before purchase

Some seats in venues may have restricted views of the stage, or other information associated with them. It’s important that the customers are made aware of any special seat conditions that will apply before they purchase. Messages can be classified as restricted view or not, but it is necessary in all cases to display these messages (sometimes we aren’t able to accurately classify a restricted view message). These messages must be displayed to the customer before they purchase, and also in the purchase confirmation that is sent to the customer.

Representative Test: User reserves any seats for a Thursday performance of Swan Lake (event 6IE)
When the reservation is made
Then the application should show that these seats have restricted views before taking payment.

For customers implementing seat selection functionality:

Representative Test: User selects seats C5 and C6 for event 7AB
When the seats are selected
Then the application should show that these seats have restricted views, and show the seat text for C6 (“Haunted seat”).

Release tickets if customer does not proceed with the booking flow

A customer may change their mind about the number or type of tickets to be reserved for a performance. If your customer selects and reserves tickets, then goes back to select and reserve additional tickets or removes the reserved tickets from their basket, the initial tickets should be released.

Representative Test: User makes a reservation for any ticket then clicks “back” and makes another selection, or removes items from their basket
When the customer selects a second reservation or empties their basket
Then your application should call the release resource of the Ingresso API. This must be done before any further call to reserve.
Optionally it should also display a message to the customer indicating the ticket reservation has been released.

Gracefully handle reservation failures and seat changes

Especially for popular shows, it is quite common that seats that are requested are purchased by other customers before they can be purchased by the user of your application. In this case, the Ingresso system will return a failure or, in some cases, continue the reservation but with different seats than you may expect.

Representative Test: User makes a reservation including seat H10 for event 7AA or 7AB
When the customer reserves seat H10 (by itself or with other seats),
Then the reservation will fail and your application should indicate that the reservation for that ticket type and price band could not be completed, and that their card has not been charged.

Representative Test: User reserves a number of seats including seat D7 for event 7AA or 7AB
When the customer reserves a number of seats including D7 on 7AB,
Then the reservation process will proceed but the seat numbers will have been changed and your application should notify the customer that the seats have changed.

Gracefully handle purchase failures

The purchase process can fail for various reasons. The purchase call will usually return a reason for failure, if known, after which the reserve status will be set to “failed” and the tickets automatically released by the backend. The reserve must be made again and the seat numbers can change, so your application must notify the customer and show the confirmation again before attempting to repurchase.

Representative Test: User attempts to purchase any number of tickets for event 6IE and enters fail part one in address line two
When the customer enters fail part one in the address line two and clicks to purchase
Then the application should attempt the purchase through the Ingresso API. When it returns the failure, a notification should be displayed to the customer and a new reservation should be made, indicating the seats may have changed.

Handle purchase timeouts

Occassionally supplier systems can suffer performance problems or outages that result in purchase requests taking a long time. In this case Ingresso will not time out. If the purchase ends up succeeding after 2 minutes we will return purchase success to you, and you will be invoiced for the tickets as normal. If you have asked Ingresso to send confirmation emails on your behalf the customer will receive an email once the purchase succeeds.

Our recommendation:

In addition to basic best-available booking flow and error handling outlined above, Ingresso recommends supporting additional functionality that will benefit your customers and help improve your user experience. The following functionality can be validated with the representative tests:

Support seat selection booking flow

For many events the backend system supports seat selection. When making a reserve for a performance, requested seats can also be passed to the API and where possible the request will be accommodated. Your application should supply an interface to allow customers to request specific seats.

Representative Test: User selects any performance for event 7AB
When the customer clicks on a performance for event 7AB
Then the application shows which seats are available (either just listing them, or using an interactive seating chart).

(Required) Seat selection respects leaving singles policy

If seat selection is supported, your interface must respect the allows_leaving_single_seats attribute set for each price band by a performance availability call. If the seat selection chosen by your customer would leave a single seat by itself in a block, and this is not allowed by the venue for the price band the seats are in, your application must indicate to the customer that this reservation will fail.

Representative Test: User opens event 7AA and selects seats B3 and B4
When the customer selects seats B3 and B4 (leaving B2 unselected)
Then the application should display a warning to the customer (preferably on the seat selection screen, but definitely prior to making a reserve call to the API).

(Required) Seat selection respects contiguous seat selection policy

Some events allow selection of discontiguous seats, and others don’t. If the event allows contiguous seat selection only, you should display a warning if the customer selects seats that are not next to each other.

Representative Test: User opens event 7AA and selects seats B3 and B5
When the customer clicks B5
Then the application should display a notification that the seat selection is invalid.

Representative Test: User opens event 7AB and selects seats B3 and B5
When the customer clicks B5
Then the booking flow should proceed as usual, because this event allows discontiguous seat selection.

Display special offers to customers

If a special offer is available for an event, it may help attract your customers. Where available, Ingresso recommends that special offers be highlighted and displayed.

Representative Test: User looks for special offers
When the customer interacts with your application (either in the main view or for an event with a special offer, such as 7AB)
Then a prominent notice is seen displaying details of the available special offers and the associated event (e.g. 7AB has 8% off CIRCLE-A seats, and no fees for STALLS-B seats).

Allow customers to select discount codes

Some events have discounted ticket prices for children, students, etc. Your customers will appreciate being able to select these discount tickets where available.

Representative Test: User requests a ticket for The Nutcracker (6IF)
When the customer requests tickets for event 6IF in Stalls-A
Then they should be able to choose between a normal ADULT ticket, and discounted CHILD, STUDENT and OAP tickets.

Display all event information to customers

Most events include additional media information. Displaying this information to your customers will help build interest and credibility.

Representative Test: User clicks on The Nutcracker (6IF)
When the customer selects the main event page or information page
Then the associated media (video, images, copy text, seating plan, etc.) will be displayed or linked.

Testing

To help with implementation and to meet the minimum and recommended functionality requirements above, we have a number of test events that you can use to validate your application and make test purchases. Many of these events also have specific conditions that can be used to test edge cases in the reservation process - please see below for details.

For testing best available events, use “Matthew Bourne’s Nutcracker TEST” (event ID = 6IF) and “Matthew Bourne’s Swan Lake test” (6IE).

For testing events that allow selection of specific seats, use either “The Unremarkable Incident of the Cat at Lunchtime” (event ID = 7AB) or “Toy Story - The Opera” (7AA).

Additionally, both events have the following conditions in common:

There is a seating plan available for 7AB and 7AA, which will be helpful if you decide to implement seat selection on your front end. Please contact us and we can talk you through how to do this.

It may be useful to use our B2B website as a working example during your development. You can sign in using your own credentials or with affiliate ID: demo and password: demopass

We have a number of other events for different types of events such as attractions and hotels - you will see these if you list all events.

Some of these other test events have specific conditions that you can check:

It can be useful to test different dispatch methods:

Live Testing

Sometimes partners wish to make test purchases of live events via our API. If you do that please ensure you:

Versioning

The API version number forms part of the URL, for example https://api.ticketswitch.com/f13/events.v1 uses version 1. We will always endeavour to add functionality and make changes in a backward-compatible manner, but when that is not possible we will implement a new version. We will then introduce a deprecation schedule for the replaced version and notify all partners that have integrated.

API Support

We only provide support to partners that we have provided a test account to. If you have a test or live account and you encounter problems with the API:

  1. Check the Ingresso status page. If there is an issue reported on the status page this indicates we are already aware.

  2. If your issue does not fit the description of the current issue, or we have not reported an issue you should contact us under the SLAs and with the contact details we have previously agreed.

Events

An event describes a product within the Ingresso system such as a theatre show, a theme park, or a sporting event. The event will also include information about the venue and its geographic location. An event will normally have one or more performances. An event without available performances will be considered dead and won’t be turn up in searches unless explicitly requested.

Each event has a unique event_id that identifies the event to other parts of the API.

There are two event-related resources:

  1. Events list: list all events or search for events.

  2. Events by ID: return detail for one or more events by their ID.

These resources are described below, followed by detail of the additional parameters that can be passed to each.

Events list

This resource lists events. It accepts a number of search parameters to filter the list returned. The list is paged to avoid large volumes of data being accidentally returned.

Definition

GET https://api.ticketswitch.com/f13/events.v1

Request

Example request

curl https://api.ticketswitch.com/f13/events.v1 \
    -u "demo:demopass" \
    -d "keywords=matthew" \
    -d "country_code=uk" \
    --compressed \
    -G
from pyticketswitch import Client

client = Client(user='demo', password='demopass')
events, meta = client.list_events(keywords=['matthew'], country_code='uk')

These are the available search / filter parameters:

Parameter Description
keywords Space separated list of search keywords, e.g. lion king new york or paris tours.
date_range Date range in the form yyyymmdd:yyyymmdd (both are optional) to filter events to those with performances within the date range.
airport_code Return events near an airport (specified using an IATA airport code)
circle Return events within in a circular geographical area. Three colon-separated values are needed for latitude, longitude, and radius in kilometres. Example: 51.52961137:-0.10601562:10.
city_code Return events in a particular city. The list of city codes can be retrieved using the cities resource.
country_code 2-digit country code (using ISO 3166-1 alpha-2).
add_dead_events Include dead events in the results. This could be useful if you dynamically retrieve the list of events from Ingresso and want to continue to display an event page after an event dies, for example to help with search engine optimisation.
offers_only If set to true the response will only include events with a special offer. Note that we rely on cached data, so we cannot guarantee complete accuracy.

These parameters are used to control the output if more than one event is returned:

Parameter Description
page_length Length of a page, default 50.
page_number Zero-indexed page number, default 0. Should be used in conjunction with the page_length parameter.
sort_order Valid values are most_popular (based on sales across all partners over the last 48 hours), alphabetic, cost_ascending (lowest price first, based on the minimum total price [seatprice + surcharge] for the event), cost_descending (highest price first, based on the maximum total price for the event), critic_rating (average critic rating, highest to lowest), recent, last_sale. When there is a tie alphabetic ordering is used to break the tie. Note: there is a slight performance impact to using cost_ascending or cost_descending if you are not also using the req_cost_range parameter.

These parameters can be passed in to request additional data for each event, and are described in more detail in the additional parameters section below:

Parameter Description
req_avail_details Returns availability details - a cached list of unique ticket types and price bands available for this event across all performances. This parameter is not commonly used.
req_avail_details_with_perfs This will add the list of available performance dates to each avail detail object. Only valid if used alongside req_avail_details.
req_avail_detail_discounts Adds non standard discounts to availability details Only valid when used alongside req_avail_details
req_cost_range Returns cost ranges - a from price and offer detail for each event. Most partners include this parameter.
req_cost_range_best_value_offer Returns the offer with the highest percentage saving. This is the most commonly used offer cost range.
req_cost_range_details Returns a list of unique ticket types and price bands and their cost ranges across all performances. This parameter is not commonly used.
req_cost_range_max_saving_offer Returns the offer with the highest absolute saving.
req_cost_range_min_cost_offer Returns the offer with the lowest cost.
req_cost_range_top_price_offer Returns the offer with the highest cost. This is the least used offer cost range.
req_cost_range_no_singles_data This returns another cost range object that excludes availability with only 1 consecutive seat available. The prices in this cost range will therefore be the same or higher than the outer cost range. It has the same structure as the main cost range (so if you want to see the “best value offer” in the no singles data, you need to add req_cost_range_best_value_offer and you will see this data in both cost ranges).
req_cost_range_discounts Adds alternate discounts to cost range data Only valid if used alongside req_cost_range
req_extra_info Returns the descriptive info for the event, returned as individual sections (structured_info) or as a single summary (event_info / event_info_html).
req_media_triplet_one Triplet one (jpg/png 520x390). See further detail on media.
req_media_triplet_two Triplet two if available (jpg/png 520x390).
req_media_triplet_three Triplet three if available (jpg/png 520x390).
req_media_triplet_four Triplet four if available (jpg/png 520x390).
req_media_triplet_five Triplet five if available (jpg/png 520x390).
req_media_seating_plan Graphical seating plan of the venue if available (jpg/png varying size).
req_media_square Small square image suitable for search or event avatar (jpg/png 140x140).
req_media_landscape Small landscape banner suitable for search (jpg/png 220x115).
req_media_marquee Large landscape banner suitable for a page heading, if available (jpg/png 700x300).
req_media_supplier Logo of the supplier/producer, if available (jpg/png varying size).
req_meta_components Returns a list of meta component events. This will only add data if the event is a “meta event” such as a touring show that is comprised of individual component events.
req_reviews Returns event reviews if available.
req_video_iframe Returns video iframe information if available.

Response

{
  "results": {
    "event": [
      {
        "city_code": "london-uk",
        "city_desc": "London",
        "classes": {
          "dance": "Ballet & Dance"
        },
        "country_code": "uk",
        "country_desc": "United Kingdom",
        "critic_review_percent": 100,
        "custom_filter": [],
        "event_desc": "Matthew Bourne's Nutcracker TEST",
        "event_id": "6IF",
        "event_path": "/6IF-matthew-bourne-s-nutcracker-test/",
        "event_status": "live",
        "event_type": "simple_ticket",
        "event_upsell_list": {
          "event_id": [
            "6IE",
            "MH0"
          ]
        },
        "event_uri_desc": "Matthew-Bourne%27s-Nutcracker-TEST",
        "geo_data": {
          "latitude": 51.52961137,
          "longitude": -0.10601562
        },
        "has_no_perfs": false,
        "is_add_on": false,
        "is_auto_quantity_add_on": false,
        "is_seated": true,
        "max_running_time": 120,
        "min_running_time": 120,
        "need_departure_date": false,
        "need_duration": false,
        "need_performance": true,
        "postcode": "EC1R 4TN",
        "show_perf_time": true,
        "source_code": "ext_test0",
        "source_desc": "External Test Backend 0",
        "user_review_percent": 100,
        "venue_desc": "Sadler's Wells",
        "venue_uri_desc": "Sadler%27s-Wells"
      },
      {
        "city_code": "london-uk",
        "city_desc": "London",
        "classes": {
          "dance": "Ballet & Dance"
        },
        "country_code": "uk",
        "country_desc": "United Kingdom",
        "custom_filter": [],
        "event_desc": "Matthew Bourne's Swan Lake test",
        "event_id": "6IE",
        "event_path": "/6IE-matthew-bourne-s-swan-lake-test/",
        "event_status": "live",
        "event_type": "simple_ticket",
        "event_upsell_list": {
          "event_id": [
            "6IF",
            "6KU",
            "MH0"
          ]
        },
        "event_uri_desc": "Matthew-Bourne%27s-Swan-Lake-test",
        "geo_data": {
          "latitude": 51.52961137,
          "longitude": -0.10601562
        },
        "has_no_perfs": false,
        "is_add_on": false,
        "is_auto_quantity_add_on": false,
        "is_seated": true,
        "max_running_time": 120,
        "min_running_time": 90,
        "need_departure_date": false,
        "need_duration": false,
        "need_performance": true,
        "postcode": "EC1R 4TN",
        "show_perf_time": true,
        "source_code": "ext_test0",
        "source_desc": "External Test Backend 0",
        "venue_desc": "Sadler's Wells",
        "venue_uri_desc": "Sadler%27s-Wells"
      }
    ],
    "paging_status": {
      "page_length": 50,
      "page_number": 0,
      "pages_remaining": 0,
      "results_remaining": 0,
      "total_unpaged_results": 2
    }
  }
}
from pyticketswitch.event import Event

[
    Event(
        id='6IF',
        status='live',
        description="Matthew Bourne's Nutcracker TEST",
        source='External Test Backend 0',
        source_code='ext_test0',
        event_type='simple_ticket',
        venue="Sadler's Wells",
        classes={
            'dance': 'Ballet & Dance'
        },
        postcode='EC1R 4TN',
        city='London',
        city_code='london-uk',
        country='United Kingdom',
        country_code='uk',
        latitude=51.52961137,
        longitude=-0.10601562,
        max_running_time=120,
        min_running_time=120,
        show_performance_time=True,
        has_performances=True,
        is_add_on=False,
        is_seated=True,
        needs_departure_date=False,
        needs_duration=False,
        needs_performance=False,
        is_auto_quantity_add_on=False,
        upsell_list=[
            '6IE',
            'MH0'
        ],
        critic_review_percent=100,
    ),
    Event(
        id='6IE',
        status='live',
        description="Matthew Bourne's Swan Lake test",
        source='External Test Backend 0',
        source_code='ext_test0',
        event_type='simple_ticket',
        venue="Sadler's Wells",
        classes={
            'dance': 'Ballet & Dance'
        },
        postcode='EC1R 4TN',
        city='London',
        city_code='london-uk',
        country='United Kingdom',
        country_code='uk',
        latitude=51.52961137,
        longitude=-0.10601562,
        max_running_time=120,
        min_running_time=90,
        show_performance_time=True,
        has_performances=True,
        is_add_on=False,
        is_seated=True,
        needs_departure_date=False,
        needs_duration=False,
        needs_performance=False,
        is_auto_quantity_add_on=False,
        upsell_list=[
            '6IF',
            '6KU',
            'MH0'
        ],
    )
]
Attribute Description
city_code Code of the city where the event is taking place.
city_desc Name of the city where the event is taking place.
classes A collection of categories (a.k.a. “classes”) that this event belongs to. The index is the class code, the value is the class description.
country_code 2-digit country code (using ISO 3166-1 alpha-2)
country_desc Name of the country where the event is taking place.
critic_review_percent The aggregate critic review score, e.g. 80 for 80%.
custom_filter Array of custom filter codes. This can be ignored by partners.
event_desc Name of the show or event e.g. The Lion King.
event_id Unique identifier for the event.
event_path If you also use a white label website this can be used to navigate to the event page, e.g. /2J5V-la-pedrera-skip-the-line/.
event_status Will be live for a normal event search. Other values are dead and pending but these will only be displayed when using the include_dead or include_non_live parameters.
event_type Currently all events are of type simple_ticket. In future we may add hotel_room and misc_item.
geo_data A block containing the following geo co-ordinates:
geo_data.latitude Latitude of the event.
geo_data.longitude Longitude of the event.
has_no_perfs true if the event has no performances. All events must have performances to be sold, so an event without performances cannot be sold and will likely soon have its event_status set to dead.
is_add_on false if this event is an add-on event. This means it can only be added to a trolley containing tickets for an event that lists this in its add_ons.
is_auto_quantity_add_on false Indicates whether add on quantity will be modified based on the number of ticket orders, if true number of addons will be equal to total number of tickets for all parent events in the trolley.
is_seated true for seated events.
max_running_time Maximum length / duration in minutes (not always present).
min_running_time Minimum length / duration in minutes (not always present).
need_departure_date Flag indicating whether the event needs a departure date specified. This is false for most events. Most partners can ignore this.
need_duration Flag indicating whether the event needs duration (specific to hotel_room events only). Most partners can ignore this.
need_performance Flag indicating if an event supports performances. For events that require a date and time to be selected this will be true. Other events, for example some attraction tickets, are valid for any date; these events will return false however they will still return a list of dummy performances - you should not present these performances to the end user but you should programmatically choose any single performance when requesting availability.
postcode Postcode of the event location.
show_perf_time false if the performance time is not relevant, for example some events use a performance description rather than specific times.
source_code Source supplier code e.g. nimax.
source_desc Source supplier description e.g. Nimax.
user_review_percent The aggregate user review score, e.g. 80 for 80%.
venue_desc Name of the venue e.g. Sadler's Wells.
venue_uri_desc URI encoded name of the venue e.g. Sadler%27s-Wells.

The outer object also contains a paging_status object:

Attribute Description
page_length The number of results per page.
page_number The zero-based page number currently displayed.
pages_remaining The number of pages that you need to request after the current page to retrieve all results.
results_remaining The number of results in the remaining pages.
total_unpaged_results The total number of results.

Events by ID

Definition

GET https://api.ticketswitch.com/f13/events_by_id.v1?event_id_list={eventidlist}

This resource returns detail for one or more specific events by their ID. It returns a dictionary of events keyed on the event’s event_id.

Example request

curl https://api.ticketswitch.com/f13/events_by_id.v1 \
    -u "demo:demopass" \
    -d "event_id_list=6IF,6IE" \
    --compressed \
    -G
from pyticketswitch import Client


client = Client(user='demo', password='demopass')
events, meta = client.get_events(event_ids=['6IF'])

Example request - with add-on and upsell events included

curl https://api.ticketswitch.com/f13/events_by_id.v1 \
    -i "demo:demopass" \
    -d "event_id_list=7AB" \
    -d "add_add_ons" \
    -d "add_upsells" \
    --compressed \
    -G
from pyticketswitch import Client


client = Client(user='demo', password='demopass')
events, meta = client.get_events(
    event_ids=['7AB'],
    with_addons=True,
    with_upsells=True,
)

Request

Parameter Description
event_id_list A comma separated list of event IDs e.g. 25DR for a single event; 1VLG,1YYO,25DR for multiple events.
add_add_ons (Optional) Include a list of add-on events per event (these are events or merchandise related to the event searched for that can be included in a trolley for upsell). It is more common to request these with add-ons
add_upsells (Optional) Include a list of upsell events per event (these are related events that the customer may be interested in as well as the base event)

These parameters can be passed in to request additional data for each event, and are described in more detail in the additional parameters section below:

Parameter Description
req_avail_details Returns availability details - a cached list of unique ticket types and price bands available for this event across all performances. This parameter is not commonly used.
req_avail_details_with_perfs This will add the list of available performance dates to each avail detail object. Only valid if used alongside req_avail_details.
req_cost_range Returns cost ranges - a from price and offer detail for each event. Most partners include this parameter.
req_cost_range_best_value_offer Returns the offer with the highest percentage saving. This is the most commonly used offer cost range.
req_cost_range_details Returns a list of unique ticket types and price bands and their cost ranges across all performances. This parameter is not commonly used.
req_cost_range_max_saving_offer Returns the offer with the highest absolute saving.
req_cost_range_min_cost_offer Returns the offer with the lowest cost.
req_cost_range_top_price_offer Returns the offer with the highest cost. This is the least used offer cost range.
req_cost_range_no_singles_data This returns another cost range object that excludes availability with only 1 consecutive seat available. The prices in this cost range will therefore be the same or higher than the outer cost range. It has the same structure as the main cost range (so if you want to see the “best value offer” in the no singles data, you need to add req_cost_range_best_value_offer and you will see this data in both cost ranges).
req_extra_info Returns the descriptive info for the event, returned as individual sections (structured_info) or as a single summary (event_info / event_info_html).
req_media_triplet_one Triplet one (jpg/png 520x390). See further detail on media.
req_media_triplet_two Triplet two if available (jpg/png 520x390).
req_media_triplet_three Triplet three if available (jpg/png 520x390).
req_media_triplet_four Triplet four if available (jpg/png 520x390).
req_media_triplet_five Triplet five if available (jpg/png 520x390).
req_media_seating_plan Graphical seating plan of the venue if available (jpg/png varying size).
req_media_square Small square image suitable for search or event avatar (jpg/png 140x140).
req_media_landscape Small landscape banner suitable for search (jpg/png 220x115).
req_media_marquee Large landscape banner suitable for a page heading, if available (jpg/png 700x300).
req_media_supplier Logo of the supplier/producer, if available (jpg/png varying size).
req_reviews Returns event reviews if available.
req_video_iframe Returns video iframe information if available.

Response

Example response

{
  "events_by_id": {
    "6IE": {
      "event": {
        "city_code": "london-uk",
        "city_desc": "London",
        "classes": {
          "dance": "Ballet & Dance"
        },
        "country_code": "uk",
        "country_desc": "United Kingdom",
        "custom_filter": [],
        "event_desc": "Matthew Bourne's Swan Lake test",
        "event_id": "6IE",
        "event_path": "/6IE-matthew-bourne-s-swan-lake-test/",
        "event_status": "live",
        "event_type": "simple_ticket",
        "event_upsell_list": {
          "event_id": [
            "6IF",
            "6KU",
            "MH0"
          ]
        },
        "event_uri_desc": "Matthew-Bourne%27s-Swan-Lake-test",
        "geo_data": {
          "latitude": 51.52961137,
          "longitude": -0.10601562
        },
        "has_no_perfs": false,
        "is_add_on": false,
        "is_auto_quantity_add_on": false,
        "is_seated": true,
        "max_running_time": 120,
        "min_running_time": 90,
        "need_departure_date": false,
        "need_duration": false,
        "need_performance": true,
        "postcode": "EC1R 4TN",
        "show_perf_time": true,
        "source_code": "ext_test0",
        "source_desc": "External Test Backend 0",
        "venue_desc": "Sadler's Wells",
        "venue_uri_desc": "Sadler%27s-Wells"
      },
      "valid_quantities": [
        1,
        2,
        3,
        4,
        5,
        6
      ],
      "venue_is_enforced": true
    },
    "6IF": {
      "event": {
        "city_code": "london-uk",
        "city_desc": "London",
        "classes": {
          "dance": "Ballet & Dance"
        },
        "country_code": "uk",
        "country_desc": "United Kingdom",
        "critic_review_percent": 100,
        "custom_filter": [],
        "event_desc": "Matthew Bourne's Nutcracker TEST",
        "event_id": "6IF",
        "event_path": "/6IF-matthew-bourne-s-nutcracker-test/",
        "event_status": "live",
        "event_type": "simple_ticket",
        "event_upsell_list": {
          "event_id": [
            "6IE",
            "MH0"
          ]
        },
        "event_uri_desc": "Matthew-Bourne%27s-Nutcracker-TEST",
        "geo_data": {
          "latitude": 51.52961137,
          "longitude": -0.10601562
        },
        "has_no_perfs": false,
        "is_add_on": false,
        "is_auto_quantity_add_on": false,
        "is_seated": true,
        "max_running_time": 120,
        "min_running_time": 120,
        "need_departure_date": false,
        "need_duration": false,
        "need_performance": true,
        "postcode": "EC1R 4TN",
        "show_perf_time": true,
        "source_code": "ext_test0",
        "source_desc": "External Test Backend 0",
        "user_review_percent": 100,
        "venue_desc": "Sadler's Wells",
        "venue_uri_desc": "Sadler%27s-Wells"
      },
      "valid_quantities": [
        1,
        2,
        3,
        4,
        5,
        6
      ],
      "venue_is_enforced": true
    }
  }
}
from pyticketswitch.event import Event

{
    '6IF': Event(
        id='6IF',
        status='live',
        description="Matthew Bourne's Nutcracker TEST",
        source='External Test Backend 0',
        source_code='ext_test0',
        event_type='simple_ticket',
        venue="Sadler's Wells",
        classes={
            'dance': 'Ballet & Dance'
        },
        postcode='EC1R 4TN',
        city='London',
        city_code='london-uk',
        country='United Kingdom',
        country_code='uk',
        latitude=51.52961137,
        longitude=-0.10601562,
        max_running_time=120,
        min_running_time=120,
        show_performance_time=True,
        has_performances=True,
        is_add_on=False,
        is_auto_quantity_add_on=False,
        is_seated=True,
        needs_departure_date=False,
        needs_duration=False,
        needs_performance=False,
        upsell_list=[
            '6IE',
            'MH0'
        ],
        critic_review_percent=100,
        valid_quantities=None,
    )
}

Example response - with add-on and upsell events included

{
  "events_by_id": {
    "7AB": {
      "add_ons": [
        {
          "city_code": "london-uk",
          "city_desc": "London",
          "classes": {
            "theatre": "Theatre"
          },
          "country_code": "uk",
          "country_desc": "United Kingdom",
          "custom_filter": [],
          "event_desc": "Unremarkable Cat Lunchbox",
          "event_id": "7AC",
          "event_path": "/7AC-unremarkable-cat-lunchbox/",
          "event_status": "live",
          "event_type": "misc_item",
          "event_uri_desc": "Unremarkable-Cat-Lunchbox",
          "geo_data": {
            "latitude": 51.49306,
            "longitude": -0.22639
          },
          "has_no_perfs": false,
          "is_add_on": true,
          "is_auto_quantity_add_on": true,
          "is_seated": false,
          "need_departure_date": false,
          "need_duration": false,
          "need_performance": false,
          "postcode": "W6 7ES",
          "show_perf_time": false,
          "source_code": "ext_test1",
          "source_desc": "External Test Backend 1",
          "venue_desc": "Lyric Apollo",
          "venue_uri_desc": "Lyric-Apollo"
        }
      ],
      "event": {
        "city_code": "london-uk",
        "city_desc": "London",
        "classes": {
          "theatre": "Theatre"
        },
        "country_code": "uk",
        "country_desc": "United Kingdom",
        "custom_filter": [],
        "event_desc": "The Unremarkable Incident of the Cat at Lunchtime",
        "event_id": "7AB",
        "event_path": "/7AB-the-unremarkable-incident-of-the-cat-at-lunchtime/",
        "event_status": "live",
        "event_type": "simple_ticket",
        "event_upsell_list": {
          "event_id": [
            "7AA",
            "6IF"
          ]
        },
        "event_uri_desc": "The-Unremarkable-Incident-of-the-Cat-at-Lunchtime",
        "geo_data": {
          "latitude": 51.49306,
          "longitude": -0.22639
        },
        "has_no_perfs": false,
        "is_add_on": false,
        "is_auto_quantity_add_on": false,
        "is_seated": true,
        "max_running_time": 90,
        "min_running_time": 90,
        "need_departure_date": false,
        "need_duration": false,
        "need_performance": true,
        "postcode": "W6 7ES",
        "show_perf_time": true,
        "source_code": "ext_test1",
        "source_desc": "External Test Backend 1",
        "venue_desc": "Lyric Apollo",
        "venue_uri_desc": "Lyric-Apollo"
      },
      "upsells": [
        {
          "city_code": "london-uk",
          "city_desc": "London",
          "classes": {
            "opera": "Opera"
          },
          "country_code": "uk",
          "country_desc": "United Kingdom",
          "custom_filter": [],
          "event_desc": "Toy Story - The Opera",
          "event_id": "7AA",
          "event_path": "/7AA-toy-story-the-opera/",
          "event_status": "live",
          "event_type": "simple_ticket",
          "event_uri_desc": "Toy-Story-The-Opera",
          "geo_data": {
            "latitude": 51.511556,
            "longitude": -0.11975
          },
          "has_no_perfs": false,
          "is_add_on": false,
          "is_auto_quantity_add_on": false,
          "is_seated": true,
          "max_running_time": 90,
          "min_running_time": 90,
          "need_departure_date": false,
          "need_duration": false,
          "need_performance": true,
          "postcode": "WC2E 7RQ",
          "show_perf_time": true,
          "source_code": "ext_test0",
          "source_desc": "External Test Backend 0",
          "venue_desc": "Lyceum Theatre",
          "venue_uri_desc": "Lyceum-Theatre"
        },
        {
          "city_code": "london-uk",
          "city_desc": "London",
          "classes": {
            "dance": "Ballet & Dance"
          },
          "country_code": "uk",
          "country_desc": "United Kingdom",
          "critic_review_percent": 100,
          "custom_filter": [],
          "event_desc": "Matthew Bourne's Nutcracker TEST",
          "event_id": "6IF",
          "event_path": "/6IF-matthew-bourne-s-nutcracker-test/",
          "event_status": "live",
          "event_type": "simple_ticket",
          "event_upsell_list": {
            "event_id": [
              "6IE"
            ]
          },
          "event_uri_desc": "Matthew-Bourne%27s-Nutcracker-TEST",
          "geo_data": {
            "latitude": 51.52961137,
            "longitude": -0.10601562
          },
          "has_no_perfs": false,
          "is_add_on": false,
          "is_auto_quantity_add_on": false,
          "is_seated": true,
          "max_running_time": 120,
          "min_running_time": 120,
          "need_departure_date": false,
          "need_duration": false,
          "need_performance": true,
          "postcode": "EC1R 4TN",
          "show_perf_time": true,
          "source_code": "ext_test0",
          "source_desc": "External Test Backend 0",
          "user_review_percent": 100,
          "venue_desc": "Sadler's Wells",
          "venue_uri_desc": "Sadler%27s-Wells"
        }
      ],
      "valid_quantities": [
        1,
        2,
        3,
        4
      ],
      "venue_is_enforced": true
    }
  }
}
from pyticketswitch.event import Event

{
    u'7AB': Event(
        min_running_time=90,
        event_type=u'simple_ticket',
        has_performances=True,
        venue_info_html=None,
        critic_review_percent=None,
        needs_departure_date=False,
        valid_quantities=None,
        addon_events=[
            Event(
                min_running_time=None,
                event_type=u'misc_item',
                has_performances=True,
                venue_info_html=None,
                critic_review_percent=None,
                needs_departure_date=False,
                valid_quantities=None,
                addon_events=None,
                availability_details=[],
                postcode=u'W6 7ES',
                country_code=u'uk',
                id=u'7AC',
                city=u'London',
                filters=[],
                media={},
                is_seated=False,
                upsell_events=None,
                event_info=None,
                content={},
                source=u'External Test Backend 1',
                max_running_time=None,
                cost_range_details=[],
                needs_performance=False,
                latitude=51.49306,
                upsell_list=[],
                city_code=u'london-uk',
                venue_addr=None,
                status=u'live',
                description=u'Unremarkable Cat Lunchbox',
                venue_addr_html=None,
                cost_range=None,
                event_info_html=None,
                source_code=u'ext_test1',
                country=u'United Kingdom',
                venue_info=None,
                venue=u'Lyric Apollo',
                longitude=-0.22639,
                is_add_on=True,
                is_auto_quantity_add_on=False,
                reviews=[],
                classes={
                    u'theatre': u'Theatre'
                },
                fields={},
                needs_duration=False,
                no_singles_cost_range=None,
                component_events=[],
                show_performance_time=False,
            )
        ],
        availability_details=[],
        postcode=u'W6 7ES',
        country_code=u'uk',
        id=u'7AB',
        city=u'London',
        filters=[],
        media={},
        is_seated=True,
        upsell_events=[
            Event(
                min_running_time=90,
                event_type=u'simple_ticket',
                has_performances=True,
                venue_info_html=None,
                critic_review_percent=None,
                needs_departure_date=False,
                valid_quantities=None,
                addon_events=None,
                availability_details=[],
                postcode=u'WC2E 7RQ',
                country_code=u'uk',
                id=u'7AA',
                city=u'London',
                filters=[],
                media={},
                is_seated=True,
                upsell_events=None,
                event_info=None,
                content={},
                source=u'External Test Backend 0',
                max_running_time=90,
                cost_range_details=[],
                needs_performance=False,
                latitude=51.511556,
                upsell_list=[],
                city_code=u'london-uk',
                venue_addr=None,
                status=u'live',
                description=u'Toy Story - The Opera',
                venue_addr_html=None,
                cost_range=None,
                event_info_html=None,
                source_code=u'ext_test0',
                country=u'United Kingdom',
                venue_info=None,
                venue=u'Lyceum Theatre',
                longitude=-0.11975,
                is_add_on=False,
                is_auto_quantity_add_on=False,
                reviews=[],
                classes={
                    u'opera': u'Opera'
                },
                fields={},
                needs_duration=False,
                no_singles_cost_range=None,
                component_events=[],
                show_performance_time=True,
            ),
            Event(
                min_running_time=120,
                event_type=u'simple_ticket',
                has_performances=True,
                venue_info_html=None,
                critic_review_percent=100,
                needs_departure_date=False,
                valid_quantities=None,
                addon_events=None,
                availability_details=[],
                postcode=u'EC1R 4TN',
                country_code=u'uk',
                id=u'6IF',
                city=u'London',
                filters=[],
                media={},
                is_seated=True,
                upsell_events=None,
                event_info=None,
                content={},
                source=u'External Test Backend 0',
                max_running_time=120,
                cost_range_details=[],
                needs_performance=False,
                latitude=51.52961137,
                upsell_list=[
                    u'6IE'
                ],
                city_code=u'london-uk',
                venue_addr=None,
                status=u'live',
                description=u"Matthew Bourne's Nutcracker TEST",
                venue_addr_html=None,
                cost_range=None,
                event_info_html=None,
                source_code=u'ext_test0',
                country=u'United Kingdom',
                venue_info=None,
                venue=u"Sadler's Wells",
                longitude=-0.10601562,
                is_add_on=False,
                is_auto_quantity_add_on=False,
                reviews=[],
                classes={
                    u'dance': u'Ballet & Dance'
                },
                fields={},
                needs_duration=False,
                no_singles_cost_range=None,
                component_events=[],
                show_performance_time=True,
            )
        ],
        event_info=None,
        content={},
        source=u'External Test Backend 1',
        max_running_time=90,
        cost_range_details=[],
        needs_performance=False,
        latitude=51.49306,
        upsell_list=[
            u'7AA',
            u'6IF'
        ],
        city_code=u'london-uk',
        venue_addr=None,
        status=u'live',
        description=u'The Unremarkable Incident of the Cat at Lunchtime',
        venue_addr_html=None,
        cost_range=None,
        event_info_html=None,
        source_code=u'ext_test1',
        country=u'United Kingdom',
        venue_info=None,
        venue=u'Lyric Apollo',
        longitude=-0.22639,
        is_add_on=False,
        is_auto_quantity_add_on=False,
        reviews=[],
        classes={
            u'theatre': u'Theatre'
        },
        fields={},
        needs_duration=False,
        no_singles_cost_range=None,
        component_events=[],
        show_performance_time=True,
    )
}

Attributes

Attribute Description
city_desc Name of the city where the event is taking place.
class Array of class or category objects.
country_code 2-digit country code (using ISO 3166-1 alpha-2).
country_desc Name of the country where the event is taking place.
critic_review_percent The aggregate critic review score, e.g. 80 for 80%.
custom_filter Array of custom filter codes. This can be ignored by partners.
date_range_start A date/time object for the start of the run.
date_range_end A date/time object for the end of the run.
event_desc Name of the show or event e.g. The Lion King.
event_id Unique identifier for the event.
event_path If you also use a white label website this can be used to navigate to the event page, e.g. /2J5V-la-pedrera-skip-the-line/.
event_status Will be live for a normal event search. Other values are dead and pending but these will only be displayed when using the include_dead or include_non_live parameters.
event_type Currently all events are of type simple_ticket. In future we may add hotel_room and misc_item.
geo_data A block containing the following geo co-ordinates:
geo_data.latitude Latitude of the event.
geo_data.longitude Longitude of the event.
has_no_perfs true if the event has no performances. For example some attraction tickets are valid for any date, so we do not present a list of performances to select.
is_add_on true if this event is an add-on event. This means it can only be added to a trolley containing tickets for an event that lists this in its add_ons.
is_seated true for seated events.
min_running_time Minimum length / duration in minutes (not always present).
max_running_time Maximum length / duration in minutes (not always present).
need_departure_date Flag indicating whether the event needs a departure date specified. This is false for most events.
need_duration Flag indicating whether the event needs duration (specific to hotel_room events only).
need_performance Flag indicating if a performance must be selected in order to retrieve availability.
postcode Postcode of the event location.
show_perf_time false if the performance time is not relevant, for example some events use a performance description rather than specific times.
source_desc Despription of the source supplier e.g. Nimax.
user_review_percent The aggregate user review score, e.g. 80 for 80%.
venue_desc Name of the venue e.g. Sadler's Wells.

Additional attributes may be specified depending on the parameters used:

Attribute Description
add_ons A list of events that can be sold as add-on events with this event
upsells A list of related events that can be upsold against this event.

— Additional parameters —

There are several additional parameters described below that can be provided to return additional data for each event.

These additional parameters require extra processing to retrieve the requested data, which will slow down the resource, sometimes substantially. They should therefore only be used where necessary.

Media

Most events include image URLs and a YouTube video. Almost all events will include the triplet_one, square and landscape images. In most cases the seating_plan, triplet_two and triplet_three images are also provided, along with a video_iframe (typically YouTube).

Request

There are several different types of media and they all need to be requested independently when using the API. When using one of the language wrappers all media requests are consolidated.

Example Request

curl https://api.ticketswitch.com/f13/events_by_id.v1 \
    -u "demo:demopass" \
    -d "event_id_list=6IF" \
    -d "req_media_triplet_one" \
    -d "req_media_triplet_two" \
    -d "req_media_triplet_three" \
    -d "req_media_triplet_four" \
    -d "req_media_triplet_five" \
    -d "req_media_seating_plan" \
    -d "req_media_square" \
    -d "req_media_landscape" \
    -d "req_media_marquee" \
    -d "req_media_supplier" \
    -d "req_video_iframe" \
    --compressed \
    -G
from pyticketswitch import Client


client = Client('demo', 'demopass')
events, meta = client.get_events(['6IF'], media=True)
Parameter Description
req_media_triplet_one Triplet one (jpg/png 520x390) - this is our most commonly used event image (ignore the “triplet” in the name which no longer makes sense…)
req_media_triplet_two Triplet two if available (jpg/png 520x390)
req_media_triplet_three Triplet three if available (jpg/png 520x390)
req_media_triplet_four Triplet four if available (jpg/png 520x390)
req_media_triplet_five Triplet five if available (jpg/png 520x390)
req_media_seating_plan Graphical seating plan of the venue if available (jpg/png varying size)
req_media_square Small square image suitable for search or event avatar (jpg/png 140x140)
req_media_landscape Small landscape banner suitable for search (jpg/png 220x115)
req_media_marquee Large landscape banner suitable for a page heading, if available (jpg/png 700x300)
req_media_supplier Logo of the supplier/producer, if available (jpg/png varying size)
req_video_iframe Returns video iframe information if available

Response

Example Response

{
  "events_by_id": {
    "6IF": {
      "event": {
        "city_code": "london-uk",
        "city_desc": "London",
        "classes": {
          "dance": "Ballet & Dance"
        },
        "country_code": "uk",
        "country_desc": "United Kingdom",
        "critic_review_percent": 100,
        "custom_filter": [],
        "event_desc": "Matthew Bourne's Nutcracker TEST",
        "event_id": "6IF",
        "event_path": "/6IF-matthew-bourne-s-nutcracker-test/",
        "event_status": "live",
        "event_type": "simple_ticket",
        "event_upsell_list": {
          "event_id": [
            "6IE",
            "MH0"
          ]
        },
        "event_uri_desc": "Matthew-Bourne%27s-Nutcracker-TEST",
        "geo_data": {
          "latitude": 51.52961137,
          "longitude": -0.10601562
        },
        "has_no_perfs": false,
        "is_add_on": false,
        "is_auto_quantity_add_on": false,
        "is_seated": true,
        "max_running_time": 120,
        "media": {
          "media_asset": [
            {
              "caption": "",
              "caption_html": "",
              "host": "d1wx4w35ubmdix.cloudfront.net",
              "insecure_complete_url": "https://d1wx4w35ubmdix.cloudfront.net/shared/event_media/cropper/93/93c04bf0d24ef3d05e8fef4ba7709df0434ea13c.jpg",
              "name": "landscape",
              "path": "/shared/event_media/cropper/93/93c04bf0d24ef3d05e8fef4ba7709df0434ea13c.jpg",
              "secure_complete_url": "https://d1wx4w35ubmdix.cloudfront.net/shared/event_media/cropper/93/93c04bf0d24ef3d05e8fef4ba7709df0434ea13c.jpg",
              "supports_http": false,
              "supports_https": true
            },
            {
              "caption": "",
              "caption_html": "",
              "host": "d1wx4w35ubmdix.cloudfront.net",
              "insecure_complete_url": "https://d1wx4w35ubmdix.cloudfront.net/shared/event_media/cropper/7e/7e048c655f79d1ae01419c92420861df156b83fc.jpg",
              "name": "marquee",
              "path": "/shared/event_media/cropper/7e/7e048c655f79d1ae01419c92420861df156b83fc.jpg",
              "secure_complete_url": "https://d1wx4w35ubmdix.cloudfront.net/shared/event_media/cropper/7e/7e048c655f79d1ae01419c92420861df156b83fc.jpg",
              "supports_http": false,
              "supports_https": true
            },
            {
              "caption": "",
              "caption_html": "",
              "host": "d1wx4w35ubmdix.cloudfront.net",
              "insecure_complete_url": "http://d1wx4w35ubmdix.cloudfront.net/shared/event_media/cropper_cloud/29/2974e58797af0d91752b73da390ae6f8fa6e4862.jpg",
              "name": "seating_plan",
              "path": "/shared/event_media/cropper_cloud/29/2974e58797af0d91752b73da390ae6f8fa6e4862.jpg",
              "secure_complete_url": "https://d1wx4w35ubmdix.cloudfront.net/shared/event_media/cropper_cloud/29/2974e58797af0d91752b73da390ae6f8fa6e4862.jpg",
              "supports_http": true,
              "supports_https": true
            },
            {
              "caption": "",
              "caption_html": "",
              "host": "d1wx4w35ubmdix.cloudfront.net",
              "insecure_complete_url": "https://d1wx4w35ubmdix.cloudfront.net/shared/event_media/cropper/5e/5e004f25b5aab6f432cd7e6839b70942d8a5f17b.jpg",
              "name": "square",
              "path": "/shared/event_media/cropper/5e/5e004f25b5aab6f432cd7e6839b70942d8a5f17b.jpg",
              "secure_complete_url": "https://d1wx4w35ubmdix.cloudfront.net/shared/event_media/cropper/5e/5e004f25b5aab6f432cd7e6839b70942d8a5f17b.jpg",
              "supports_http": false,
              "supports_https": true
            },
            {
              "caption": "",
              "caption_html": "",
              "host": "d1wx4w35ubmdix.cloudfront.net",
              "insecure_complete_url": "http://d1wx4w35ubmdix.cloudfront.net/shared/event_media/ext_test0/+system_ext_test0/supplier.jpg",
              "name": "supplier",
              "path": "/shared/event_media/ext_test0/+system_ext_test0/supplier.jpg",
              "secure_complete_url": "https://d1wx4w35ubmdix.cloudfront.net/shared/event_media/ext_test0/+system_ext_test0/supplier.jpg",
              "supports_http": true,
              "supports_https": true
            },
            {
              "caption": "",
              "caption_html": "",
              "host": "d1wx4w35ubmdix.cloudfront.net",
              "insecure_complete_url": "https://d1wx4w35ubmdix.cloudfront.net/shared/event_media/cropper/f9/f9aaf4bc04477c303d78bc5107cc0754df846ac8.jpg",
              "name": "triplet_five",
              "path": "/shared/event_media/cropper/f9/f9aaf4bc04477c303d78bc5107cc0754df846ac8.jpg",
              "secure_complete_url": "https://d1wx4w35ubmdix.cloudfront.net/shared/event_media/cropper/f9/f9aaf4bc04477c303d78bc5107cc0754df846ac8.jpg",
              "supports_http": false,
              "supports_https": true
            },
            {
              "caption": "",
              "caption_html": "",
              "host": "d1wx4w35ubmdix.cloudfront.net",
              "insecure_complete_url": "https://d1wx4w35ubmdix.cloudfront.net/shared/event_media/cropper/f9/f9aaf4bc04477c303d78bc5107cc0754df846ac8.jpg",
              "name": "triplet_four",
              "path": "/shared/event_media/cropper/f9/f9aaf4bc04477c303d78bc5107cc0754df846ac8.jpg",
              "secure_complete_url": "https://d1wx4w35ubmdix.cloudfront.net/shared/event_media/cropper/f9/f9aaf4bc04477c303d78bc5107cc0754df846ac8.jpg",
              "supports_http": false,
              "supports_https": true
            },
            {
              "caption": "",
              "caption_html": "",
              "host": "d1wx4w35ubmdix.cloudfront.net",
              "insecure_complete_url": "http://d1wx4w35ubmdix.cloudfront.net/shared/event_media/cropper_cloud/0e/0e255d4f96bd02baa7bfd22fd2cab90c8f6ced34.jpg",
              "name": "triplet_one",
              "path": "/shared/event_media/cropper_cloud/0e/0e255d4f96bd02baa7bfd22fd2cab90c8f6ced34.jpg",
              "secure_complete_url": "https://d1wx4w35ubmdix.cloudfront.net/shared/event_media/cropper_cloud/0e/0e255d4f96bd02baa7bfd22fd2cab90c8f6ced34.jpg",
              "supports_http": true,
              "supports_https": true
            },
            {
              "caption": "",
              "caption_html": "",
              "host": "d1wx4w35ubmdix.cloudfront.net",
              "insecure_complete_url": "http://d1wx4w35ubmdix.cloudfront.net/shared/event_media/cropper_cloud/ca/ca2d4589a89480514f0db6fcec8a982652280093.jpg",
              "name": "triplet_two",
              "path": "/shared/event_media/cropper_cloud/ca/ca2d4589a89480514f0db6fcec8a982652280093.jpg",
              "secure_complete_url": "https://d1wx4w35ubmdix.cloudfront.net/shared/event_media/cropper_cloud/ca/ca2d4589a89480514f0db6fcec8a982652280093.jpg",
              "supports_http": true,
              "supports_https": true
            }
          ]
        },
        "min_running_time": 120,
        "need_departure_date": false,
        "need_duration": false,
        "need_performance": true,
        "postcode": "EC1R 4TN",
        "show_perf_time": true,
        "source_code": "ext_test0",
        "source_desc": "External Test Backend 0",
        "user_review_percent": 100,
        "venue_desc": "Sadler's Wells",
        "venue_uri_desc": "Sadler%27s-Wells",
        "video_iframe": {
          "video_iframe_caption": "",
          "video_iframe_caption_html": "",
          "video_iframe_height": 315,
          "video_iframe_host": "www.youtube.com",
          "video_iframe_path": "/embed/G1JpEHGizk4?rel=0",
          "video_iframe_supports_http": false,
          "video_iframe_supports_https": true,
          "video_iframe_url_when_insecure": "https://www.youtube.com/embed/G1JpEHGizk4?rel=0",
          "video_iframe_url_when_secure": "https://www.youtube.com/embed/G1JpEHGizk4?rel=0",
          "video_iframe_width": 420
        }
      },
      "valid_quantities": [
        1,
        2,
        3,
        4,
        5,
        6
      ],
      "venue_is_enforced": true
    }
  }
}
from pyticketswitch.media import Media
from pyticketswitch.event import Event

{
    '6IF': Event(
        id='6IF',
        status='live',
        description="Matthew Bourne's Nutcracker TEST",
        source='External Test Backend 0',
        source_code='ext_test0',
        event_type='simple_ticket',
        venue="Sadler's Wells",
        classes={
            'dance': 'Ballet & Dance'
        },
        postcode='EC1R 4TN',
        city='London',
        city_code='london-uk',
        country='United Kingdom',
        country_code='uk',
        latitude=51.52961137,
        longitude=-0.10601562,
        max_running_time=120,
        min_running_time=120,
        show_performance_time=True,
        has_performances=True,
        is_add_on=false,
        is_auto_quantity_add_on=false,
        is_seated=True,
        needs_departure_date=False,
        needs_duration=False,
        needs_performance=False,
        upsell_list=[
            '6IE',
            'MH0'
        ],
        media={
            'landscape': Media(
                caption='',
                caption_html='',
                name='landscape',
                url='https://d1wx4w35ubmdix.cloudfront.net/media/event/6IF/matthew-bournes-nutcracker-test-landscape-M2kz.jpg?versionId=C3UX_j98L2FWDOof4BCY15QyKrBJ0ZRR',
                secure=True,
                width=None,
                height=None,
            ),
            'marquee': Media(
                caption='',
                caption_html='',
                name='marquee',
                url='https://d1wx4w35ubmdix.cloudfront.net/media/event/6IF/matthew-bournes-nutcracker-test-marquee-bGIw.jpg?versionId=WwcyqyDnuxFwYgare_6Omy61AACpF8hG',
                secure=True,
                width=None,
                height=None,
            ),
            'seating_plan': Media(
                caption='',
                caption_html='',
                name='seating_plan',
                url='https://d1wx4w35ubmdix.cloudfront.net/media/event/6IF/matthew-bournes-nutcracker-test-seating-plan-dzJ3.jpg',
                secure=True,
                width=None,
                height=None,
            ),
            'square': Media(
                caption='',
                caption_html='',
                name='square',
                url='https://d1wx4w35ubmdix.cloudfront.net/media/event/6IF/matthew-bournes-nutcracker-test-square-Z0Jk.jpg?versionId=09daZJn.14RH7.84cRKXK2FfODDmFYpC',
                secure=True,
                width=None,
                height=None,
            ),
            'triplet_four': Media(
                caption='',
                caption_html='',
                name='triplet_four',
                url='https://d1wx4w35ubmdix.cloudfront.net/media/event/6IF/matthew-bournes-nutcracker-test-triplet-four-bndw.jpg?versionId=kz.Y.qd379E_wm2ZNWnGRMtLFu4Teqpu',
                secure=True,
                width=None,
                height=None,
            ),
            'triplet_one': Media(
                caption='',
                caption_html='',
                name='triplet_one',
                url='https://d1wx4w35ubmdix.cloudfront.net/media/event/6IF/matthew-bournes-nutcracker-test-triplet-one-eWVq.jpg?versionId=WewM3wJOwzhP.QOsJqDSBUDxBwimxNV_',
                secure=True,
                width=None,
                height=None,
            ),
            'triplet_three': Media(
                caption='',
                caption_html='',
                name='triplet_three',
                url='https://d1wx4w35ubmdix.cloudfront.net/media/event/6IF/matthew-bournes-nutcracker-test-triplet-three-U2Yz.jpg?versionId=MPJgrknmvajkTolWT55cmh7McDrI4PCD',
                secure=True,
                width=None,
                height=None,
            ),
            'triplet_two': Media(
                caption='',
                caption_html='',
                name='triplet_two',
                url='https://d1wx4w35ubmdix.cloudfront.net/media/event/6IF/matthew-bournes-nutcracker-test-triplet-two-d0xl.jpg?versionId=FpaMhCJw.gCmiOn598.m3OmtXJv5p0OM',
                secure=True,
                width=None,
                height=None,
            ),
            'video': Media(
                caption='',
                caption_html='',
                name='video',
                url='https://www.youtube.com/embed/G1JpEHGizk4?rel=0',
                secure=True,
                width=420,
                height=315,
            )
        },
        critic_review_percent=100,
    )
}

Media Asset

Media assets provide both secure and insecure URLs where possible when either a secure or and insecure URL is not available, the other URL will be substituted. Generally speaking all our media assets at this point will be https with no http option, however this is not a universal rule.

Attribute Description
name The name of the image, default names are `triple_{one
caption any text related to the image in plain text
caption_html any text related to the image in html
host the hostname of server on which the image is hosted
path the absolute path of the file on the host
insecure_complete_url a complete http address
secure_complete_url a complete https address
supports_http indicates that the asset is accessible via http
supports_https indicates that the asset is accessible via https

Video iframe

The video iframe is a slightly different media asset that contains information about an embeddable video related to the event. It shares the same attributes with a regular media asset but also contains hints for iframe sizing.

Attribute Description
video_iframe_height the suggested height of the iframe
video_iframe_width the suggested width of the iframe
video_iframe_caption any text related to the image in plain text
video_iframe_caption_html any text related to the image in html
video_iframe_host the hostname of server on which the image is hosted
video_iframe_path the absolute path of the file on the host
video_iframe_insecure_complete_url a complete http address
video_iframe_secure_complete_url a complete https address
video_iframe_supports_http indicates that the asset is accessible via http
video_iframe_supports_https indicates that the asset is accessible via https

Extra info

Most events will have additional information and content available. This data is not returned by default because it can slow down response time, especially when many events are being returned.

Request

Example request


curl https://api.ticketswitch.com/f13/events_by_id.v1 \
    -u "demo:demopass" \
    -d "event_id_list=6IF" \
    -d "req_extra_info" \
    --compressed \
    -G
from pyticketswitch import Client


client = Client('demo', 'demopass')
events, meta = client.get_events(['6IF'], extra_info=True)
Parameter Description
req_extra_info Returns the descriptive info for the event, returned as individual sections (structured_info) and as a single summary (event_info / event_info_html)

Response

Example response

{
  "events_by_id": {
    "6IF": {
      "event": {
        "city_code": "london-uk",
        "city_desc": "London",
        "classes": {
          "dance": "Ballet & Dance"
        },
        "country_code": "uk",
        "country_desc": "United Kingdom",
        "critic_review_percent": 100,
        "custom_filter": [],
        "event_desc": "Matthew Bourne's Nutcracker TEST",
        "event_id": "6IF",
        "event_info": "Matthew Bourne's stunning production of Nutcracker! returns in 2008 to Sadler's Wells having broken all box office records during last year's sell-out season.\n\nThis festive treat is full of his trademark style of wit, pathos and theatrical magic. Nutcracker! follows Clara's journey from a bleak Christmas Eve at Dr.Dross' Orphanage, through a shimmering ice-skating wonderland and to the spectacular candy folk of Sweetieland.\n\nOliver award-winning designer Anthony Ward and Tchaikovsky's much-loved score combined with sizzling choreography guarantee that Matthew Bourne's Nutcracker! is a fresh, lip-smacking, serving of traditional Christmas fare.\n\nMatthew Bourne has achieved both artistic and commercial success with his imaginative new versions of classical ballets. Last year his Play Without Words made for the Royal National Theatre, received two Olivier Awards and is shortly to be revived.\n\nDuration\n\nA Goldilocks duration - not too long, not too short, just the right amount of time.\n\n\nPerformance Times\n\nAnytime you like! As long as there's a show on...\n\n\nWhere Do I Go\n\nTo Sadler's Wells of course!\n\n\nWhat's Included\n\nEverything you need.\n\n\nGood To Know\n\nWarning! Men in very tight tights.\n\n\nSuitable For Children\n\nSure, just be aware of the aforementioned tights.\n\n\nOffers Information\n\nThis is some offers information\n\n",
        "event_info_html": "<div><p>Matthew Bourne's stunning production of Nutcracker! returns in 2008 to Sadler's Wells having broken all box office records during last year's sell-out season.</p>\r\n<p>This festive treat is full of his trademark style of wit, pathos and theatrical magic. Nutcracker! follows Clara's journey from a bleak Christmas Eve at Dr.Dross' Orphanage, through a shimmering ice-skating wonderland and to the spectacular candy folk of Sweetieland.</p>\r\n<p>Oliver award-winning designer Anthony Ward and Tchaikovsky's much-loved score combined with sizzling choreography guarantee that Matthew Bourne's Nutcracker! is a fresh, lip-smacking, serving of traditional Christmas fare.</p>\r\n<p>Matthew Bourne has achieved both artistic and commercial success with his imaginative new versions of classical ballets. Last year his Play Without Words made for the Royal National Theatre, received two Olivier Awards and is shortly to be revived.</p></div>\n\n<h4>Duration</h4>\n<div><p>A Goldilocks duration - not <em>too</em> long, not <em>too</em> short, just the right amount of time.</p></div>\n\n<h4>Performance Times</h4>\n<div><p>Anytime you like! As long as there's a show on...</p></div>\n\n<h4>Where Do I Go</h4>\n<div><p>To Sadler's Wells of course!</p></div>\n\n<h4>What&#39;s Included</h4>\n<div><p>Everything you need.</p></div>\n\n<h4>Good To Know</h4>\n<div><p>Warning! Men in very tight tights.</p></div>\n\n<h4>Suitable For Children</h4>\n<div><p>Sure, just be aware of the aforementioned tights.</p></div>\n\n<h4>Offers Information</h4>\n<div><p>This is some offers information</p></div>\n",
        "event_path": "/6IF-matthew-bourne-s-nutcracker-test/",
        "event_status": "live",
        "event_type": "simple_ticket",
        "event_upsell_list": {
          "event_id": [
            "6IE",
            "MH0"
          ]
        },
        "event_uri_desc": "Matthew-Bourne%27s-Nutcracker-TEST",
        "geo_data": {
          "latitude": 51.52961137,
          "longitude": -0.10601562
        },
        "has_no_perfs": false,
        "is_add_on": false,
        "is_auto_quantity_add_on": false,
        "is_seated": true,
        "max_running_time": 120,
        "min_running_time": 120,
        "need_departure_date": false,
        "need_duration": false,
        "need_performance": true,
        "postcode": "EC1R 4TN",
        "show_perf_time": true,
        "source_code": "ext_test0",
        "source_desc": "External Test Backend 0",
        "structured_info": {
          "address": {
            "name": "Address",
            "value": "Roseberry Avenue\r\nIslington\r\nLondon\r\nUK",
            "value_html": "<p>Roseberry Avenue\r\nIslington\r\nLondon\r\nUK</p>"
          },
          "duration": {
            "name": "Duration",
            "value": "A Goldilocks duration - not too long, not too short, just the right amount of time.\n",
            "value_html": "<p>A Goldilocks duration - not <em>too</em> long, not <em>too</em> short, just the right amount of time.</p>"
          },
          "good_to_know": {
            "name": "Good To Know",
            "value": "Warning! Men in very tight tights.\n",
            "value_html": "<p>Warning! Men in very tight tights.</p>"
          },
          "offers": {
            "name": "Offers Information",
            "value": "This is some offers information\n",
            "value_html": "<p>This is some offers information</p>"
          },
          "overview": {
            "name": "Overview",
            "value": "Matthew Bourne's stunning production of Nutcracker! returns in 2008 to Sadler's Wells having broken all box office records during last year's sell-out season.\n\nThis festive treat is full of his trademark style of wit, pathos and theatrical magic. Nutcracker! follows Clara's journey from a bleak Christmas Eve at Dr.Dross' Orphanage, through a shimmering ice-skating wonderland and to the spectacular candy folk of Sweetieland.\n\nOliver award-winning designer Anthony Ward and Tchaikovsky's much-loved score combined with sizzling choreography guarantee that Matthew Bourne's Nutcracker! is a fresh, lip-smacking, serving of traditional Christmas fare.\n\nMatthew Bourne has achieved both artistic and commercial success with his imaginative new versions of classical ballets. Last year his Play Without Words made for the Royal National Theatre, received two Olivier Awards and is shortly to be revived.\n",
            "value_html": "<p>Matthew Bourne's stunning production of Nutcracker! returns in 2008 to Sadler's Wells having broken all box office records during last year's sell-out season.</p>\r\n<p>This festive treat is full of his trademark style of wit, pathos and theatrical magic. Nutcracker! follows Clara's journey from a bleak Christmas Eve at Dr.Dross' Orphanage, through a shimmering ice-skating wonderland and to the spectacular candy folk of Sweetieland.</p>\r\n<p>Oliver award-winning designer Anthony Ward and Tchaikovsky's much-loved score combined with sizzling choreography guarantee that Matthew Bourne's Nutcracker! is a fresh, lip-smacking, serving of traditional Christmas fare.</p>\r\n<p>Matthew Bourne has achieved both artistic and commercial success with his imaginative new versions of classical ballets. Last year his Play Without Words made for the Royal National Theatre, received two Olivier Awards and is shortly to be revived.</p>"
          },
          "pricing_details_info": {
            "name": "Pricing details information",
            "value": "Book by 30th April for performances from 10 July - 10 August and pay no booking fee on this show\n",
            "value_html": "<p>Book by 30th April for performances from 10 July - 10 August and pay no booking fee on this show</p>"
          },
          "suitable_for_children": {
            "name": "Suitable For Children",
            "value": "Sure, just be aware of the aforementioned tights.\n",
            "value_html": "<p>Sure, just be aware of the aforementioned tights.</p>"
          },
          "whats_included": {
            "name": "What's Included",
            "value": "Everything you need.\n",
            "value_html": "<p>Everything you need.</p>"
          },
          "when_can_i_go": {
            "name": "Performance Times",
            "value": "Anytime you like! As long as there's a show on...\n",
            "value_html": "<p>Anytime you like! As long as there's a show on...</p>"
          },
          "where_do_i_go": {
            "name": "Where Do I Go",
            "value": "To Sadler's Wells of course!\n",
            "value_html": "<p>To Sadler's Wells of course!</p>"
          }
        },
        "user_review_percent": 100,
        "venue_addr": "Roseberry Avenue\r\nIslington\r\nLondon\r\nUK",
        "venue_addr_html": "<div><p>Roseberry Avenue\r\nIslington\r\nLondon\r\nUK</p></div>\n",
        "venue_desc": "Sadler's Wells",
        "venue_uri_desc": "Sadler%27s-Wells"
      },
      "valid_quantities": [
        1,
        2,
        3,
        4,
        5,
        6
      ],
      "venue_is_enforced": true
    }
  }
}
from pyticketswitch.content import Content
from pyticketswitch.event import Event

{
    '6IF': Event(
        id='6IF',
        status='live',
        description="Matthew Bourne's Nutcracker TEST",
        source='External Test Backend 0',
        source_code='ext_test0',
        event_type='simple_ticket',
        venue="Sadler's Wells",
        classes={
            'dance': 'Ballet & Dance'
        },
        filters=[

        ],
        postcode='EC1R 4TN',
        city='London',
        city_code='london-uk',
        country='United Kingdom',
        country_code='uk',
        latitude=51.52961137,
        longitude=-0.10601562,
        max_running_time=120,
        min_running_time=120,
        show_performance_time=True,
        has_performances=True,
        is_add_on=False,
        is_auto_quantity_add_on=False,
        is_seated=True,
        needs_departure_date=False,
        needs_duration=False,
        needs_performance=False,
        upsell_list=[
            '6IE',
            'MH0'
        ],
        content={
            'address': Content(
                name='Address',
                value='Roseberry Avenue Islington London UK\n',
                value_html='<p>Roseberry Avenue Islington London UK</p>',
            ),
            'duration': Content(
                name='Duration',
                value='A Goldilocks duration - not too long, not too short, just the right amount of time.\n',
                value_html='<p>A Goldilocks duration - not <em>too</em> long, not <em>too</em> short, just the right amount of time.</p>',
            ),
            'good_to_know': Content(
                name='Good To Know',
                value='Warning! Men in very tight tights.\n',
                value_html='<p>Warning! Men in very tight tights.</p>',
            ),
            'offers': Content(
                name='Offers Information',
                value='This is some offers information\n',
                value_html='<p>This is some offers information</p>',
            ),
            'overview': Content(
                name='Overview',
                value="Matthew Bourne's stunning production of Nutcracker! returns in 2008 to Sadler's Wells having broken all box office records during last year's sell-out season.\n\nThis festive treat is full of his trademark style of wit, pathos and theatrical magic. Nutcracker! follows Clara's journey from a bleak Christmas Eve at Dr.Dross' Orphanage, through a shimmering ice-skating wonderland and to the spectacular candy folk of Sweetieland.\n\nOliver award-winning designer Anthony Ward and Tchaikovsky's much-loved score combined with sizzling choreography guarantee that Matthew Bourne's Nutcracker! is a fresh, lip-smacking, serving of traditional Christmas fare.\n\nMatthew Bourne has achieved both artistic and commercial success with his imaginative new versions of classical ballets. Last year his Play Without Words made for the Royal National Theatre, received two Olivier Awards and is shortly to be revived.\n",
                value_html="<p>Matthew Bourne's stunning production of Nutcracker! returns in 2008 to Sadler's Wells having broken all box office records during last year's sell-out season.</p>\r\n<p>This festive treat is full of his trademark style of wit, pathos and theatrical magic. Nutcracker! follows Clara's journey from a bleak Christmas Eve at Dr.Dross' Orphanage, through a shimmering ice-skating wonderland and to the spectacular candy folk of Sweetieland.</p>\r\n<p>Oliver award-winning designer Anthony Ward and Tchaikovsky's much-loved score combined with sizzling choreography guarantee that Matthew Bourne's Nutcracker! is a fresh, lip-smacking, serving of traditional Christmas fare.</p>\r\n<p>Matthew Bourne has achieved both artistic and commercial success with his imaginative new versions of classical ballets. Last year his Play Without Words made for the Royal National Theatre, received two Olivier Awards and is shortly to be revived.</p>",
            ),
            'pricing_details_info': Content(
                name='Pricing details information',
                value='Book by 30th April for performances from 10 July - 10 August and pay no booking fee on this show\n',
                value_html='<p>Book by 30th April for performances from 10 July - 10 August and pay no booking fee on this show</p>',
            ),
            'suitable_for_children': Content(
                name='Suitable For Children',
                value='Sure, just be aware of the aforementioned tights.\n',
                value_html='<p>Sure, just be aware of the aforementioned tights.</p>',
            ),
            'whats_included': Content(
                name="What's Included",
                value='Everything you need.\n',
                value_html='<p>Everything you need.</p>',
            ),
            'when_can_i_go': Content(
                name='Performance Times',
                value="Anytime you like! As long as there's a show on...\n",
                value_html="<p>Anytime you like! As long as there's a show on...</p>",
            ),
            'where_do_i_go': Content(
                name='Where Do I Go',
                value="To Sadler's Wells of course!\n",
                value_html="<p>To Sadler's Wells of course!</p>",
            )
        },
        event_info="Matthew Bourne's stunning production of Nutcracker! returns in 2008 to Sadler's Wells having broken all box office records during last year's sell-out season.\n\nThis festive treat is full of his trademark style of wit, pathos and theatrical magic. Nutcracker! follows Clara's journey from a bleak Christmas Eve at Dr.Dross' Orphanage, through a shimmering ice-skating wonderland and to the spectacular candy folk of Sweetieland.\n\nOliver award-winning designer Anthony Ward and Tchaikovsky's much-loved score combined with sizzling choreography guarantee that Matthew Bourne's Nutcracker! is a fresh, lip-smacking, serving of traditional Christmas fare.\n\nMatthew Bourne has achieved both artistic and commercial success with his imaginative new versions of classical ballets. Last year his Play Without Words made for the Royal National Theatre, received two Olivier Awards and is shortly to be revived.\n\nDuration\n\nA Goldilocks duration - not too long, not too short, just the right amount of time.\n\n\nPerformance Times\n\nAnytime you like! As long as there's a show on...\n\n\nWhere Do I Go\n\nTo Sadler's Wells of course!\n\n\nWhat's Included\n\nEverything you need.\n\n\nGood To Know\n\nWarning! Men in very tight tights.\n\n\nSuitable For Children\n\nSure, just be aware of the aforementioned tights.\n\n\nOffers Information\n\nThis is some offers information\n\n",
        event_info_html="<div><p>Matthew Bourne's stunning production of Nutcracker! returns in 2008 to Sadler's Wells having broken all box office records during last year's sell-out season.</p>\r\n<p>This festive treat is full of his trademark style of wit, pathos and theatrical magic. Nutcracker! follows Clara's journey from a bleak Christmas Eve at Dr.Dross' Orphanage, through a shimmering ice-skating wonderland and to the spectacular candy folk of Sweetieland.</p>\r\n<p>Oliver award-winning designer Anthony Ward and Tchaikovsky's much-loved score combined with sizzling choreography guarantee that Matthew Bourne's Nutcracker! is a fresh, lip-smacking, serving of traditional Christmas fare.</p>\r\n<p>Matthew Bourne has achieved both artistic and commercial success with his imaginative new versions of classical ballets. Last year his Play Without Words made for the Royal National Theatre, received two Olivier Awards and is shortly to be revived.</p></div>\n\n<h4>Duration</h4>\n<div><p>A Goldilocks duration - not <em>too</em> long, not <em>too</em> short, just the right amount of time.</p></div>\n\n<h4>Performance Times</h4>\n<div><p>Anytime you like! As long as there's a show on...</p></div>\n\n<h4>Where Do I Go</h4>\n<div><p>To Sadler's Wells of course!</p></div>\n\n<h4>What&#39;s Included</h4>\n<div><p>Everything you need.</p></div>\n\n<h4>Good To Know</h4>\n<div><p>Warning! Men in very tight tights.</p></div>\n\n<h4>Suitable For Children</h4>\n<div><p>Sure, just be aware of the aforementioned tights.</p></div>\n\n<h4>Offers Information</h4>\n<div><p>This is some offers information</p></div>\n",
        venue_addr='Roseberry Avenue Islington London UK\n',
        venue_addr_html='<div><p>Roseberry Avenue Islington London UK</p></div>\n',
        critic_review_percent=100,
    )
}
Attribute Description
content this is miscellaneous textual content that can be used to populate an event page.
event_info summary description of the event as plain text
event_info_html summary description of the event as html
venue_info summary description of the venue as plain text
venue_info_html summary description of the venue as html
venue_addr the address of the venue as plain text
venue_addr_html the address of the venue as html

Reviews

We expose critic reviews for events that have them.

Request

Example Request

curl https://api.ticketswitch.com/f13/events_by_id.v1 \
    -u "demo:demopass" \
    -d "event_id_list=6IF" \
    -d "req_reviews" \
    --compressed \
    -G
from pyticketswitch import Client


client = Client('demo', 'demopass')
events, meta = client.get_events(['6IF'], reviews=True)
Parameter Description
req_reviews Returns event reviews if available

Response

Example Response

{
  "events_by_id": {
    "6IF": {
      "event": {
        "city_code": "london-uk",
        "city_desc": "London",
        "classes": {
          "dance": "Ballet & Dance"
        },
        "country_code": "uk",
        "country_desc": "United Kingdom",
        "critic_review_percent": 100,
        "custom_filter": [],
        "event_desc": "Matthew Bourne's Nutcracker TEST",
        "event_id": "6IF",
        "event_path": "/6IF-matthew-bourne-s-nutcracker-test/",
        "event_status": "live",
        "event_type": "simple_ticket",
        "event_upsell_list": {
          "event_id": [
            "6IE",
            "MH0"
          ]
        },
        "event_uri_desc": "Matthew-Bourne%27s-Nutcracker-TEST",
        "geo_data": {
          "latitude": 51.52961137,
          "longitude": -0.10601562
        },
        "has_no_perfs": false,
        "is_add_on": false,
        "is_auto_quantity_add_on": false,
        "is_seated": true,
        "max_running_time": 120,
        "min_running_time": 120,
        "need_departure_date": false,
        "need_duration": false,
        "need_performance": true,
        "postcode": "EC1R 4TN",
        "reviews": {
          "review": [
            {
              "is_user_review": false,
              "review_author": "The Times",
              "review_body": "Cannot recommend this show enough!",
              "review_date_desc": "Tue, 17th November 2015",
              "review_iso8601_date_and_time": "2015-11-17T10:00:00Z",
              "review_lang": "en",
              "review_original_url": "",
              "review_time_desc": "10.00 AM",
              "review_title": "Unmissable!",
              "star_rating": 5
            },
            {
              "is_user_review": true,
              "review_author": "Matt Allpress",
              "review_body": "What a show! The mise-en-scène is magical, the choreography is wonderful, the story is magnificent and those tights... incredible. I'll be buying tickets for this show again and again",
              "review_date_desc": "Thu, 28th August 2014",
              "review_iso8601_date_and_time": "2014-08-28T10:00:00Z",
              "review_lang": "en",
              "review_original_url": "",
              "review_time_desc": "10.00 AM",
              "review_title": "Can't get enough!",
              "star_rating": 5
            }
          ]
        },
        "show_perf_time": true,
        "source_code": "ext_test0",
        "source_desc": "External Test Backend 0",
        "user_review_percent": 100,
        "venue_desc": "Sadler's Wells",
        "venue_uri_desc": "Sadler%27s-Wells"
      },
      "valid_quantities": [
        1,
        2,
        3,
        4,
        5,
        6
      ],
      "venue_is_enforced": true
    }
  }
}
from pyticketswitch.review import Review
from pyticketswitch.event import Event

{
    '6IF': Event(
        id='6IF',
        status='live',
        description="Matthew Bourne's Nutcracker TEST",
        source='External Test Backend 0',
        source_code='ext_test0',
        event_type='simple_ticket',
        venue="Sadler's Wells",
        classes={
            'dance': 'Ballet & Dance'
        },
        postcode='EC1R 4TN',
        city='London',
        city_code='london-uk',
        country='United Kingdom',
        country_code='uk',
        latitude=51.52961137,
        longitude=-0.10601562,
        max_running_time=120,
        min_running_time=120,
        show_performance_time=True,
        has_performances=True,
        is_add_on=False,
        is_auto_quantity_add_on=False,
        is_seated=True,
        needs_departure_date=False,
        needs_duration=False,
        needs_performance=False,
        upsell_list=[
            '6IE',
            'MH0'
        ],
        reviews=[
            Review(
                body='Cannot recommend this show enough!',
                date_time=datetime.datetime(2015, 11, 17, 10, 0, tzinfo=tzutc()),
                star_rating=5,
                language='en',
                title='Unmissable!',
                is_user=False,
                author='The Times',
                url='',
            ),
            Review(
                body="What a show! The mise-en-scène is magical, the choreography is wonderful, the story is magnificent and those tights... incredible. I'll be buying tickets for this show again and again",
                date_time=datetime.datetime(2014, 8, 28, 10, 0, tzinfo=tzutc()),
                star_rating=5,
                language='en',
                title="Can't get enough!",
                is_user=True,
                author='Matt Allpress',
                url='',
            )
        ],
        critic_review_percent=100,
    )
}
Attribute Description
is_user_review false for critic reviews; true for user reviews
review_author The reviewer - for critic reviews this is normally the name of a newspaper e.g. The Evening Standard
review_body The main review content - for critic reviews this is typically a quote from the review
review_date_desc Review date
review_iso8601_date_and_time review date and time in ISO 8601 format
review_lang The ISO 639 language code of the review
review_original_url For critic reviews we sometimes record the original source of the review quote
review_time_desc Review time
review_title Review title, not always present
star_rating A rating between 1 and 5 (5 is best)

Cost range

Cost ranges are a cached summary of the pricing that has been seen for your username. They are primarily used to retrieve the minimum (or “from”) price for the event, along with detail of any offers or discounts. They allow you to display a from price and details of offers for your event, so most partners request cost ranges.

Cost ranges are generated from availability requests made either by end-users or by scheduled processes that Ingresso use to update cost range data. You should not attempt to make multiple availability requests in order to keep this data up to date - please contact us instead to discuss options. Cost ranges are only ever returned as part of a parent object (such as event).

Request

Example request

curl https://api.ticketswitch.com/f13/events_by_id.v1 \
    -u "demo:demopass" \
    -d "event_id_list=6L9" \
    -d "req_cost_range" \
    -d "req_cost_range_best_value_offer" \
    -d "req_cost_range_max_saving_offer" \
    -d "req_cost_range_min_cost_offer" \
    -d "req_cost_range_top_price_offer" \
    -d "req_cost_range_no_singles_data" \
    --compressed \
    -G
from pyticketswitch import Client


client = Client('demo', 'demopass')
events, meta = client.get_events(
    event_ids=['6IF'],
    cost_range=True,
    best_value_offer=True,
    max_saving_offer=True,
    min_cost_offer=True,
    top_price_offer=True,
    no_singles_data=True,
)

On its own, req_cost_range will add min and max prices only, however by adding one of the other 5 parameters below you can receive additional data (multiple parameters are provided because different partners can have different definitions of the “best” offer). Most API users request cost ranges.

Parameter Description
req_cost_range Returns cost ranges for each event.
req_cost_range_best_value_offer Returns the offer with the highest percentage saving. This is the most commonly used offer cost range.
req_cost_range_max_saving_offer Returns the offer with the highest absolute saving.
req_cost_range_min_cost_offer Returns the offer with the lowest cost.
req_cost_range_top_price_offer Returns the offer with the highest cost. This is the least used offer cost range.
req_cost_range_no_singles_data This returns another cost range object that excludes availability with only one consecutive seat available. The prices in this cost range will therefore be the same or higher than the outer cost range. It has the same structure as the main cost range (so if you want to see the “best value offer” in the no singles data, you need to add req_cost_range_best_value_offer and you will see this data in both cost ranges).

Response

Example response

{
  "currency_details": {
    "usd": {
      "currency_code": "usd",
      "currency_factor": 100,
      "currency_number": 840,
      "currency_places": 2,
      "currency_post_symbol": "",
      "currency_pre_symbol": "$"
    }
  },
  "events_by_id": {
    "6L9": {
      "event": {
        "city_code": "las_vegas-us",
        "city_desc": "Las Vegas",
        "classes": {
          "circuscabaret": "Circus, Cabaret & Variety"
        },
        "cost_range": {
          "best_value_offer": {
            "absolute_saving": 9,
            "full_seatprice": 75,
            "full_surcharge": 5,
            "offer_seatprice": 68,
            "offer_surcharge": 3,
            "percentage_saving": 11
          },
          "max_saving_offer": {
            "absolute_saving": 9,
            "full_seatprice": 75,
            "full_surcharge": 5,
            "offer_seatprice": 68,
            "offer_surcharge": 3,
            "percentage_saving": 11
          },
          "max_seatprice": 68,
          "max_surcharge": 3,
          "min_cost_offer": {
            "absolute_saving": 9,
            "full_seatprice": 75,
            "full_surcharge": 5,
            "offer_seatprice": 68,
            "offer_surcharge": 3,
            "percentage_saving": 11
          },
          "min_seatprice": 68,
          "min_surcharge": 3,
          "range_currency_code": "usd",
          "top_price_offer": {
            "absolute_saving": 9,
            "full_seatprice": 75,
            "full_surcharge": 5,
            "offer_seatprice": 68,
            "offer_surcharge": 3,
            "percentage_saving": 11
          },
          "valid_quantities": [
            1,
            2,
            3,
            4
          ]
        },
        "country_code": "us",
        "country_desc": "United States of America",
        "custom_filter": [],
        "event_desc": "La Femme",
        "event_id": "6L9",
        "event_path": "/6L9-la-femme/",
        "event_status": "live",
        "event_type": "simple_ticket",
        "event_uri_desc": "La-Femme",
        "geo_data": {
          "latitude": 36.1034,
          "longitude": -115.1721
        },
        "has_no_perfs": false,
        "is_add_on": false,
        "is_auto_quantity_add_on": false,
        "is_seated": true,
        "max_running_time": 120,
        "min_running_time": 90,
        "need_departure_date": false,
        "need_duration": false,
        "need_performance": true,
        "postcode": "NV89109",
        "show_perf_time": true,
        "source_code": "ext_test1",
        "source_desc": "External Test Backend 1",
        "venue_desc": "MGM Grand Las Vegas",
        "venue_uri_desc": "MGM-Grand-Las-Vegas"
      },
      "valid_quantities": [
        1,
        2,
        3,
        4
      ],
      "venue_is_enforced": true
    }
  }
}
from pyticketswitch.cost_range import CostRange
from pyticketswitch.event import Event

{
    '6IF': Event(
        id='6IF',
        status='live',
        description="Matthew Bourne's Nutcracker TEST",
        source='External Test Backend 0',
        source_code='ext_test0',
        event_type='simple_ticket',
        venue="Sadler's Wells",
        classes={
            'dance': 'Ballet & Dance'
        },
        postcode='EC1R 4TN',
        city='London',
        city_code='london-uk',
        country='United Kingdom',
        country_code='uk',
        latitude=51.52961137,
        longitude=-0.10601562,
        max_running_time=120,
        min_running_time=120,
        show_performance_time=True,
        has_performances=True,
        is_add_on=False,
        is_auto_quantity_add_on=False,
        is_seated=True,
        needs_departure_date=False,
        needs_duration=False,
        needs_performance=False,
        upsell_list=[
            '6IE',
            'MH0'
        ],
        cost_range=CostRange(
            valid_quantities=[
                1,
                2,
                3,
                4,
                5,
                6
            ],
            max_seatprice=47.0,
            max_surcharge=5.0,
            min_seatprice=18.0,
            min_surcharge=3.0,
            currency='gbp',
        ),
        no_singles_cost_range=CostRange(
            valid_quantities=[
                1,
                2,
                3,
                4,
                5,
                6
            ],
            max_seatprice=47.0,
            max_surcharge=5.0,
            min_seatprice=18.0,
            min_surcharge=3.0,
            currency='gbp',
        ),
        critic_review_percent=100,
    )
}

Each event returned includes a cost_range object with the following attributes:

Attribute Description
best_value_offer The offer with the highest percentage saving. This is the most commonly used offer cost range.
max_saving_offer The offer with the highest absolute saving.
max_seatprice The per-ticket face value for the highest price (seatprice + surcharge)
max_surcharge The per-ticket booking fee for the highest price (seatprice + surcharge)
min_cost_offer The offer with the lowest cost.
min_seatprice The per-ticket face value for the lowest price (seatprice + surcharge)
min_surcharge The per-ticket booking fee for the lowest price (seatprice + surcharge)
no_singles_cost_range This returns another cost range object that excludes availability with only one consecutive seat available. The prices in this cost range will therefore be the same as or higher than the outer cost range.
range_currency_code The currency code for the cost range - further detail for the currency can be found in the currency_details object, described below.
top_price_offer The offer with the highest cost. This is the least used offer cost range.
valid_quantities An array of ticket quantities with availability.

The offer objects contain the following attributes:

Attribute Description
absolute_saving Defined as (full_seatprice + full_surcharge) - (offer_seatprice + offer_surcharge).
full_seatprice The non-offer per-ticket face value.
full_surcharge The non-offer per-ticket booking fee.
offer_seatprice The offer per-ticket face value.
offer_surcharge The offer per-ticket booking fee.
percentage_saving Defined as absolute_saving / (full_seatprice + full_surcharge) * 100.

The outer object includes a currency_details object containing one currency object (indexed on the currency code) for every currency referenced in the JSON response. Each currency has the following attributes:

Attribute Description
currency_code ISO 4217 three letter code
currency_factor Multiply by this number to get values in the base unit (e.g. multiplying $47.11 by the currency_factor will give 4711 cents)
currency_number ISO 4217 numeric identifier
currency_places The number of decimal places to display (eg 45.5 usd should be displayed as 45.50)
currency_post_symbol A symbol to display at the end of the price
currency_pre_symbol A symbol to display in front of the price

Cost range details

Cost range details presents a cost range for every available price band. They allow you for example display a list of price bands on a show page, before the customer begins to choose their tickets. This is not a commonly used feature.

A list of ticket types are returned; nested within each ticket type are the available price bands; nested within each price band is a cost range. Cost range details are only ever returned as part of the parent event object.

Request

Example request

curl https://api.ticketswitch.com/f13/events_by_id.v1 \
    -u "demo:demopass" \
    -d "event_id_list=6IF" \
    -d "req_cost_range_details" \
    --compressed \
    -G
from pyticketickswitch import client

client = Client('demo', 'demopass')
events, meta = client.get_events(['6IF'], cost_range_details=True)

req_cost_range_details is the main parameter that switches on cost range details. The other parameters listed can also be included to return additional cost range data.

Parameter Description
req_cost_range_details Returns a list of unique ticket types and price bands and their cost ranges across all performances
req_cost_range_best_value_offer Returns the offer with the highest percentage saving. This is the most commonly used offer cost range.
req_cost_range_max_saving_offer Returns the offer with the highest absolute saving.
req_cost_range_min_cost_offer Returns the offer with the lowest cost.
req_cost_range_top_price_offer Returns the offer with the highest cost. This is the least used offer cost range.
req_cost_range_no_singles_data This returns another cost range object that excludes availability with only one consecutive seat available. The prices in this cost range will therefore be the same or higher than the outer cost range. It has the same structure as the main cost range (so if you want to see the “best value offer” in the no singles data, you need to add req_cost_range_best_value_offer and you will see this data in both cost ranges).

Response

Example response

{
  "currency_details": {
    "gbp": {
      "currency_code": "gbp",
      "currency_factor": 100,
      "currency_number": 826,
      "currency_places": 2,
      "currency_post_symbol": "",
      "currency_pre_symbol": "£"
    }
  },
  "events_by_id": {
    "6IF": {
      "event": {
        "city_code": "london-uk",
        "city_desc": "London",
        "classes": {
          "dance": "Ballet & Dance"
        },
        "cost_range_details": {
          "ticket_type": [
            {
              "price_band": [
                {
                  "cost_range": {
                    "max_seatprice": 47,
                    "max_surcharge": 5,
                    "min_seatprice": 47,
                    "min_surcharge": 5,
                    "range_currency_code": "gbp",
                    "valid_quantities": [
                      1,
                      2,
                      3,
                      4,
                      5,
                      6
                    ]
                  },
                  "price_band_code": "A",
                  "price_band_desc": ""
                }
              ],
              "ticket_type_code": "BALCONY",
              "ticket_type_desc": "Balcony"
            },
            {
              "price_band": [
                {
                  "cost_range": {
                    "max_seatprice": 35,
                    "max_surcharge": 4,
                    "min_seatprice": 35,
                    "min_surcharge": 4,
                    "range_currency_code": "gbp",
                    "valid_quantities": [
                      1,
                      2,
                      3,
                      4,
                      5,
                      6
                    ]
                  },
                  "price_band_code": "A",
                  "price_band_desc": ""
                },
                {
                  "cost_range": {
                    "max_seatprice": 30,
                    "max_surcharge": 4,
                    "min_seatprice": 30,
                    "min_surcharge": 4,
                    "range_currency_code": "gbp",
                    "valid_quantities": [
                      1,
                      2,
                      3,
                      4,
                      5,
                      6
                    ]
                  },
                  "price_band_code": "B",
                  "price_band_desc": ""
                },
                {
                  "cost_range": {
                    "max_seatprice": 25,
                    "max_surcharge": 4,
                    "min_seatprice": 25,
                    "min_surcharge": 4,
                    "range_currency_code": "gbp",
                    "valid_quantities": [
                      1,
                      2,
                      3,
                      4,
                      5,
                      6
                    ]
                  },
                  "price_band_code": "C",
                  "price_band_desc": ""
                }
              ],
              "ticket_type_code": "CIRCLE",
              "ticket_type_desc": "Upper circle"
            },
            {
              "price_band": [
                {
                  "cost_range": {
                    "max_seatprice": 21,
                    "max_surcharge": 3,
                    "min_seatprice": 21,
                    "min_surcharge": 3,
                    "range_currency_code": "gbp",
                    "valid_quantities": [
                      1,
                      2,
                      3,
                      4,
                      5,
                      6
                    ]
                  },
                  "price_band_code": "A",
                  "price_band_desc": ""
                },
                {
                  "cost_range": {
                    "max_seatprice": 18,
                    "max_surcharge": 3,
                    "min_seatprice": 18,
                    "min_surcharge": 3,
                    "range_currency_code": "gbp",
                    "valid_quantities": [
                      1,
                      2,
                      3
                    ]
                  },
                  "price_band_code": "B",
                  "price_band_desc": ""
                }
              ],
              "ticket_type_code": "STALLS",
              "ticket_type_desc": "Stalls"
            }
          ]
        },
        "country_code": "uk",
        "country_desc": "United Kingdom",
        "critic_review_percent": 100,
        "custom_filter": [],
        "event_desc": "Matthew Bourne's Nutcracker TEST",
        "event_id": "6IF",
        "event_path": "/6IF-matthew-bourne-s-nutcracker-test/",
        "event_status": "live",
        "event_type": "simple_ticket",
        "event_upsell_list": {
          "event_id": [
            "6IE",
            "MH0"
          ]
        },
        "event_uri_desc": "Matthew-Bourne%27s-Nutcracker-TEST",
        "geo_data": {
          "latitude": 51.52961137,
          "longitude": -0.10601562
        },
        "has_no_perfs": false,
        "is_add_on": false, 
        "is_auto_quantity_add_on": false,
        "is_seated": true,
        "max_running_time": 120,
        "min_running_time": 120,
        "need_departure_date": false,
        "need_duration": false,
        "need_performance": true,
        "postcode": "EC1R 4TN",
        "show_perf_time": true,
        "source_code": "ext_test0",
        "source_desc": "External Test Backend 0",
        "user_review_percent": 100,
        "venue_desc": "Sadler's Wells",
        "venue_uri_desc": "Sadler%27s-Wells"
      },
      "valid_quantities": [
        1,
        2,
        3,
        4,
        5,
        6
      ],
      "venue_is_enforced": true
    }
  }
}
from pyticketswitch.event import Event
from pyticketswitch.ticket_type import TicketType
from pyticketswitch.discount import Discount
from pyticketswitch.cost_range import CostRange
from pyticketswitch.price_band import PriceBand

{
    '6IF': Event(
        id='6IF',
        status='live',
        description="Matthew Bourne's Nutcracker TEST",
        source='External Test Backend 0',
        source_code='ext_test0',
        event_type='simple_ticket',
        venue="Sadler's Wells",
        classes={
            'dance': 'Ballet & Dance'
        },
        postcode='EC1R 4TN',
        city='London',
        city_code='london-uk',
        country='United Kingdom',
        country_code='uk',
        latitude=51.52961137,
        longitude=-0.10601562,
        max_running_time=120,
        min_running_time=120,
        show_performance_time=True,
        has_performances=True,
        is_add_on=False,
        is_auto_quantity_add_on=False,
        is_seated=True,
        needs_departure_date=False,
        needs_duration=False,
        needs_performance=False,
        upsell_list=[
            '6IE',
            'MH0'
        ],
        cost_range_details=[
            TicketType(
                code='BALCONY',
                description='Balcony',
                price_bands=[
                    PriceBand(
                        code='A',
                        description='',
                        cost_range=CostRange(
                            valid_quantities=[
                                1,
                                2,
                                3,
                                4,
                                5,
                                6
                            ],
                            max_seatprice=47.0,
                            max_surcharge=5.0,
                            min_seatprice=47.0,
                            min_surcharge=5.0,
                            currency='gbp',
                        ),
                        allows_leaving_single_seats='always',
                        example_seats_are_real=True,
                    )
                ],
            ),
            TicketType(
                code='CIRCLE',
                description='Upper circle',
                price_bands=[
                    PriceBand(
                        code='A',
                        description='',
                        cost_range=CostRange(
                            valid_quantities=[
                                1,
                                2,
                                3,
                                4,
                                5,
                                6
                            ],
                            max_seatprice=35.0,
                            max_surcharge=4.0,
                            min_seatprice=35.0,
                            min_surcharge=4.0,
                            currency='gbp',
                        ),
                        allows_leaving_single_seats='always',
                        example_seats_are_real=True,
                    ),
                    PriceBand(
                        code='B',
                        description='',
                        cost_range=CostRange(
                            valid_quantities=[
                                1,
                                2,
                                3,
                                4,
                                5,
                                6
                            ],
                            max_seatprice=30.0,
                            max_surcharge=4.0,
                            min_seatprice=30.0,
                            min_surcharge=4.0,
                            currency='gbp',
                        ),
                        allows_leaving_single_seats='always',
                        example_seats_are_real=True,
                    ),
                    PriceBand(
                        code='C',
                        description='',
                        cost_range=CostRange(
                            valid_quantities=[
                                1,
                                2,
                                3,
                                4,
                                5,
                                6
                            ],
                            max_seatprice=25.0,
                            max_surcharge=4.0,
                            min_seatprice=25.0,
                            min_surcharge=4.0,
                            currency='gbp',
                        ),
                        allows_leaving_single_seats='always',
                        example_seats_are_real=True,
                    )
                ],
            ),
            TicketType(
                code='STALLS',
                description='Stalls',
                price_bands=[
                    PriceBand(
                        code='A',
                        description='',
                        cost_range=CostRange(
                            valid_quantities=[
                                1,
                                2,
                                3,
                                4,
                                5,
                                6
                            ],
                            max_seatprice=21.0,
                            max_surcharge=3.0,
                            min_seatprice=21.0,
                            min_surcharge=3.0,
                            currency='gbp',
                        ),
                        allows_leaving_single_seats='always',
                        example_seats_are_real=True,
                    ),
                    PriceBand(
                        code='B',
                        description='',
                        cost_range=CostRange(
                            valid_quantities=[
                                1,
                                2,
                                3
                            ],
                            max_seatprice=18.0,
                            max_surcharge=3.0,
                            min_seatprice=18.0,
                            min_surcharge=3.0,
                            currency='gbp',
                        ),
                        allows_leaving_single_seats='always',
                        example_seats_are_real=True,
                    )
                ],
            )
        ],
        critic_review_percent=100,
    )
}

The cost_range_details object includes an array of ticket types that describe a part of house or location within the venue.

Attribute Description
ticket_type_code the identifier of the ticket type, this can be used later in the trolley or reserve resource.
ticket_type_desc A human readable description of the ticket type if applicable
price_band an array of price bands

Price bands describe the different levels of pricing that are available within a ticket type. It’s important to note that a price band may not have a long term set price, and as such ticket prices and surcharges might change on a performance to performance basis.

Attribute Description
price_band_code the identifier of the price band, this can be used later in the trolley or reserve resource.
price_band_desc A human readable description of the price band if applicable
cost_range The cost range for this price band.

The cost range has the following attributes:

Attribute Description
best_value_offer The offer with the highest percentage saving. This is the most commonly used offer cost range.
max_saving_offer The offer with the highest absolute saving.
max_seatprice The per-ticket face value for the highest price (seatprice + surcharge)
max_surcharge The per-ticket booking fee for the highest price (seatprice + surcharge)
min_cost_offer The offer with the lowest cost.
min_seatprice The per-ticket face value for the lowest price (seatprice + surcharge)
min_surcharge The per-ticket booking fee for the lowest price (seatprice + surcharge)
no_singles_cost_range This returns another cost range object that excludes availability with only one consecutive seat available. The prices in this cost range will therefore be the same as or higher than the outer cost range.
quantity_options The ticket quantities that have availability.
range_currency_code The currency code for the cost range - further detail for the currency can be found in the currency_details object, described below.
top_price_offer The offer with the highest cost. This is the least used offer cost range.

The offer objects contain the following attributes:

Attribute Description
absolute_saving Defined as (full_seatprice + full_surcharge) - (offer_seatprice + offer_surcharge).
full_seatprice The non-offer per-ticket face value.
full_surcharge The non-offer per-ticket booking fee.
offer_seatprice The offer per-ticket face value.
offer_surcharge The offer per-ticket booking fee.
percentage_saving Defined as absolute_saving / (full_seatprice + full_surcharge) * 100.

The outer object includes a currency_details object containing one currency object (indexed on the currency code) for every currency referenced in the JSON response. Each currency has the following attributes:

Attribute Description
currency_code ISO 4217 three letter code
currency_factor Multiply by this number to get values in the base unit (e.g. multiplying $47.11 by the currency_factor will give 4711 cents)
currency_number ISO 4217 numeric identifier
currency_places The number of decimal places to display (eg 45.5 usd should be displayed as 45.50)
currency_post_symbol A symbol to display at the end of the price
currency_pre_symbol A symbol to display in front of the price

Availability details

Availability details are a cached list of the price bands available for an event across all performances. They are cached from previous availability requests made via your username. This data can be useful for example if you wish to display a separate page with pricing detail for all price bands on sale.

Availability details are generated from availability requests made either by end-users or by scheduled processes that Ingresso use to update this data. You should not attempt to make multiple availability requests in order to keep this data up to date - please contact us instead to discuss options

Request

Example request

curl https://api.ticketswitch.com/f13/events_by_id.v1 \
    -u "demo:demopass" \
    -d "event_id_list=6IF" \
    -d "req_avail_details" \
    -d "req_avail_details_with_perfs" \
    --compressed \
    -G
from pyticketickswitch import client

client = Client('demo', 'demopass')
events, meta = client.get_events(['6IF'], availability=True, availability_with_performances=True)
Parameter Description
req_avail_details Returns a list of unique ticket types and price bands that are available for this event across all performances. This parameter is not commonly used.
req_avail_details_with_perfs This will add the list of available performance dates to each avail detail object. Only valid if used alongside req_avail_details

Response

Example Response

{
  "currency_details": {
    "gbp": {
      "currency_code": "gbp",
      "currency_factor": 100,
      "currency_number": 826,
      "currency_places": 2,
      "currency_post_symbol": "",
      "currency_pre_symbol": "£"
    }
  },
  "events_by_id": {
    "6IF": {
      "event": {
        "avail_details": {
          "ticket_type": [
            {
              "price_band": [
                {
                  "avail_detail": [
                    {
                      "avail_currency_code": "gbp",
                      "available_dates": {
                        "first_yyyymmdd": "20170309",
                        "last_yyyymmdd": "20170705",
                        "year_2017": {
                          "apr_bitmask": 803192702,
                          "jul_bitmask": 30,
                          "jun_bitmask": 1065287163,
                          "mar_bitmask": 2130574080,
                          "may_bitmask": 2079846367
                        }
                      },
                      "available_weekdays_bitmask": 63,
                      "seatprice": 47,
                      "surcharge": 5,
                      "valid_quantities": [
                        1,
                        2,
                        3,
                        4,
                        5,
                        6
                      ]
                    }
                  ],
                  "price_band_code": "A",
                  "price_band_desc": ""
                }
              ],
              "ticket_type_code": "BALCONY",
              "ticket_type_desc": "Balcony"
            },
            {
              "price_band": [
                {
                  "avail_detail": [
                    {
                      "avail_currency_code": "gbp",
                      "available_dates": {
                        "first_yyyymmdd": "20170309",
                        "last_yyyymmdd": "20170705",
                        "year_2017": {
                          "apr_bitmask": 803192702,
                          "jul_bitmask": 30,
                          "jun_bitmask": 1065287163,
                          "mar_bitmask": 2130574080,
                          "may_bitmask": 2079846367
                        }
                      },
                      "available_weekdays_bitmask": 63,
                      "seatprice": 35,
                      "surcharge": 4,
                      "valid_quantities": [
                        1,
                        2,
                        3,
                        4,
                        5,
                        6
                      ]
                    }
                  ],
                  "price_band_code": "A",
                  "price_band_desc": ""
                },
                {
                  "avail_detail": [
                    {
                      "avail_currency_code": "gbp",
                      "available_dates": {
                        "first_yyyymmdd": "20170309",
                        "last_yyyymmdd": "20170705",
                        "year_2017": {
                          "apr_bitmask": 803192702,
                          "jul_bitmask": 30,
                          "jun_bitmask": 1065287163,
                          "mar_bitmask": 2130574080,
                          "may_bitmask": 2079846367
                        }
                      },
                      "available_weekdays_bitmask": 63,
                      "seatprice": 30,
                      "surcharge": 4,
                      "valid_quantities": [
                        1,
                        2,
                        3,
                        4,
                        5,
                        6
                      ]
                    }
                  ],
                  "price_band_code": "B",
                  "price_band_desc": ""
                },
                {
                  "avail_detail": [
                    {
                      "avail_currency_code": "gbp",
                      "available_dates": {
                        "first_yyyymmdd": "20170309",
                        "last_yyyymmdd": "20170705",
                        "year_2017": {
                          "apr_bitmask": 803192702,
                          "jul_bitmask": 30,
                          "jun_bitmask": 1065287163,
                          "mar_bitmask": 2130574080,
                          "may_bitmask": 2079846367
                        }
                      },
                      "available_weekdays_bitmask": 63,
                      "seatprice": 25,
                      "surcharge": 4,
                      "valid_quantities": [
                        1,
                        2,
                        3,
                        4,
                        5,
                        6
                      ]
                    }
                  ],
                  "price_band_code": "C",
                  "price_band_desc": ""
                }
              ],
              "ticket_type_code": "CIRCLE",
              "ticket_type_desc": "Upper circle"
            },
            {
              "price_band": [
                {
                  "avail_detail": [
                    {
                      "avail_currency_code": "gbp",
                      "available_dates": {
                        "first_yyyymmdd": "20170309",
                        "last_yyyymmdd": "20170705",
                        "year_2017": {
                          "apr_bitmask": 803192702,
                          "jul_bitmask": 30,
                          "jun_bitmask": 1065287163,
                          "mar_bitmask": 2130574080,
                          "may_bitmask": 2079846367
                        }
                      },
                      "available_weekdays_bitmask": 63,
                      "seatprice": 21,
                      "surcharge": 3,
                      "valid_quantities": [
                        1,
                        2,
                        3,
                        4,
                        5,
                        6
                      ]
                    }
                  ],
                  "price_band_code": "A",
                  "price_band_desc": ""
                },
                {
                  "avail_detail": [
                    {
                      "avail_currency_code": "gbp",
                      "available_dates": {
                        "first_yyyymmdd": "20170309",
                        "last_yyyymmdd": "20170705",
                        "year_2017": {
                          "apr_bitmask": 803192702,
                          "jul_bitmask": 30,
                          "jun_bitmask": 1065287163,
                          "mar_bitmask": 2130574080,
                          "may_bitmask": 2079846367
                        }
                      },
                      "available_weekdays_bitmask": 63,
                      "seatprice": 18,
                      "surcharge": 3,
                      "valid_quantities": [
                        1,
                        2,
                        3
                      ]
                    }
                  ],
                  "price_band_code": "B",
                  "price_band_desc": ""
                }
              ],
              "ticket_type_code": "STALLS",
              "ticket_type_desc": "Stalls"
            }
          ]
        },
        "city_code": "london-uk",
        "city_desc": "London",
        "classes": {
          "dance": "Ballet & Dance"
        },
        "country_code": "uk",
        "country_desc": "United Kingdom",
        "critic_review_percent": 100,
        "custom_filter": [],
        "event_desc": "Matthew Bourne's Nutcracker TEST",
        "event_id": "6IF",
        "event_path": "/6IF-matthew-bourne-s-nutcracker-test/",
        "event_status": "live",
        "event_type": "simple_ticket",
        "event_upsell_list": {
          "event_id": [
            "6IE",
            "MH0"
          ]
        },
        "event_uri_desc": "Matthew-Bourne%27s-Nutcracker-TEST",
        "geo_data": {
          "latitude": 51.52961137,
          "longitude": -0.10601562
        },
        "has_no_perfs": false,
        "is_add_on": false,
        "is_auto_quantity_add_on": false,
        "is_seated": true,
        "max_running_time": 120,
        "min_running_time": 120,
        "need_departure_date": false,
        "need_duration": false,
        "need_performance": true,
        "postcode": "EC1R 4TN",
        "show_perf_time": true,
        "source_code": "ext_test0",
        "source_desc": "External Test Backend 0",
        "user_review_percent": 100,
        "venue_desc": "Sadler's Wells",
        "venue_uri_desc": "Sadler%27s-Wells"
      },
      "valid_quantities": [
        1,
        2,
        3,
        4,
        5,
        6
      ],
      "venue_is_enforced": true
    }
  }
}
from pyticketswitch.availability import AvailabilityDetails
from pyticketswitch.event import Event

{
    '6IF': Event(
        id='6IF',
        status='live',
        description="Matthew Bourne's Nutcracker TEST",
        source='External Test Backend 0',
        source_code='ext_test0',
        event_type='simple_ticket',
        venue="Sadler's Wells",
        classes={
            'dance': 'Ballet & Dance'
        },
        postcode='EC1R 4TN',
        city='London',
        city_code='london-uk',
        country='United Kingdom',
        country_code='uk',
        latitude=51.52961137,
        longitude=-0.10601562,
        max_running_time=120,
        min_running_time=120,
        show_performance_time=True,
        has_performances=True,
        is_add_on=False,
        is_auto_quantity_add_on=False,
        is_seated=True,
        needs_departure_date=False,
        needs_duration=False,
        needs_performance=False,
        upsell_list=[
            '6IE',
            'MH0'
        ],
        critic_review_percent=100,
        availability_details=[
            AvailabilityDetails(
                ticket_type='BALCONY',
                ticket_type_description='Balcony',
                price_band='A',
                price_band_description='',
                seatprice=47.0,
                surcharge=5.0,
                full_seatprice=0.0,
                full_surcharge=0.0,
                percentage_saving=0.0,
                absolute_saving=0.0,
                currency='gbp',
                first_date=datetime.date(2017, 5, 3),
                last_date=datetime.date(2017, 8, 30),
            ),
            AvailabilityDetails(
                ticket_type='STALLS',
                ticket_type_description='Stalls',
                price_band='B',
                price_band_description='',
                seatprice=18.0,
                surcharge=3.0,
                full_seatprice=0.0,
                full_surcharge=0.0,
                percentage_saving=0.0,
                absolute_saving=0.0,
                currency='gbp',
                first_date=datetime.date(2017, 5, 3),
                last_date=datetime.date(2017, 8, 30),
            ),
            AvailabilityDetails(
                ticket_type='STALLS',
                ticket_type_description='Stalls',
                price_band='A',
                price_band_description='',
                seatprice=21.0,
                surcharge=3.0,
                full_seatprice=0.0,
                full_surcharge=0.0,
                percentage_saving=0.0,
                absolute_saving=0.0,
                currency='gbp',
                first_date=datetime.date(2017, 5, 3),
                last_date=datetime.date(2017, 8, 30),
            ),
            AvailabilityDetails(
                ticket_type='CIRCLE',
                ticket_type_description='Upper circle',
                price_band='C',
                price_band_description='',
                seatprice=25.0,
                surcharge=4.0,
                full_seatprice=0.0,
                full_surcharge=0.0,
                percentage_saving=0.0,
                absolute_saving=0.0,
                currency='gbp',
                first_date=datetime.date(2017, 5, 3),
                last_date=datetime.date(2017, 8, 30),
            ),
            AvailabilityDetails(
                ticket_type='CIRCLE',
                ticket_type_description='Upper circle',
                price_band='B',
                price_band_description='',
                seatprice=30.0,
                surcharge=4.0,
                full_seatprice=0.0,
                full_surcharge=0.0,
                percentage_saving=0.0,
                absolute_saving=0.0,
                currency='gbp',
                first_date=datetime.date(2017, 5, 3),
                last_date=datetime.date(2017, 8, 30),
            ),
            AvailabilityDetails(
                ticket_type='CIRCLE',
                ticket_type_description='Upper circle',
                price_band='A',
                price_band_description='',
                seatprice=35.0,
                surcharge=4.0,
                full_seatprice=0.0,
                full_surcharge=0.0,
                percentage_saving=0.0,
                absolute_saving=0.0,
                currency='gbp',
                first_date=datetime.date(2017, 5, 3),
                last_date=datetime.date(2017, 8, 30),
            )
        ],
    )

Ticket types describe a part of house or location within the venue.

Attribute Description
ticket_type_code The identifier of the ticket type, this can be used later in the trolley or reserve resource.
ticket_type_desc A human readable description of the price band if applicable.
price_band A list of price bands.

Price bands describe the different levels of pricing that are available within a ticket type. It’s important to note that a price band may not have a long term set price, and as such ticket prices and surcharges might change on a performance to performance basis.

Attribute Description
price_band_code The identifier of the price band, this can be used later in the trolley or reserve resource.
price_band_desc A human readable description of the price band if applicable.
avail_details A list of the prices in this price band and when they are available.

The avail details indicate which prices we have seen and when they are expected to be available. If the req_avail_details_with_perfs parameter was included then the availability details will include information on what performances where available with that price.

Attribute Description
avail_currency_code The currency code for the price - further detail for the currency can be found in the currency_details object, described below.
available_dates first_yyyymmdd and last_yyyymmdd for the range, and year_YYYY includes a bitmask for each month of the year (if, for example, the jan_bitmask is 1959 (i.e. “11110100111”) this means there is availability on the following days of the month only: 1,2,3,6,8,9,10,11).
available_weekdays_bitmask The days of the week where we have seen availability - see the example in the bitmask fields explanation.
seatprice The per-ticket face value.
surcharge The per-ticket booking fee.
valid_quantities An array of available quantities we have seen for this price band.

The outer object includes a currency_details object containing one currency object (indexed on the currency code) for every currency referenced in the JSON response. Each currency has the following attributes:

Attribute Description
currency_code ISO 4217 three letter code
currency_factor Multiply by this number to get values in the base unit (e.g. multiplying $47.11 by the currency_factor will give 4711 cents)
currency_number ISO 4217 numeric identifier
currency_places The number of decimal places to display (eg 45.5 usd should be displayed as 45.50)
currency_post_symbol A symbol to display at the end of the price
currency_pre_symbol A symbol to display in front of the price

Performances

A performance describes an instance of an event, for example the Saturday 21st January 7.30pm showing of The Lion King. This is the case for the majority of our product, however since not all events (and the systems we connect to) are the same, there are some exceptions:

An event is considered live when it has one or more future performances. The API will not return performances that are more than 2 years in the future by calendar date.

There are two performance-related resources:

  1. Performances list: list performances for an event.

  2. Performances by ID: return detail for one or more performances by their ID.

These two resources are described below, followed by detail of the extra parameters that can be passed in to each resource.

Performances list

Definition

GET https://api.ticketswitch.com/f13/performances.v1?event_id={eventid}

This call returns a list of performances for a particular event. The list is paged to avoid large volumes of data being accidentally returned.

Typical use cases:

Request

Example request

curl https://api.ticketswitch.com/f13/performances.v1 \
    -u "demo:demopass" \
    -d "event_id=6IF" \
    -d "page_length=10" \
    --compressed \
    -G
from pyticketswitch import Client

client = Client('demo', 'demopass')
performances, meta = client.list_performances('6IF')
Parameter Description
event_id Identifier of the event you want to see performances for.
page_length Length of a page, default 50.
page_number Page number, default 0, ignored if page_len is not present.
date_range Date range in the form yyyymmdd:yyyymmdd (both are optional)

These parameters can be passed in to request additional data for each performance, and are described in more detail in the extra parameters section below:

Parameter Description
req_avail_details Returns availability details - a cached list of unique ticket types and price bands available for this performance. This parameter is not commonly used.
req_avail_detail_discounts Adds non standard discounts to availability details Only valid when used alongside req_avail_details
req_cost_range Returns cost ranges - a from price and offer detail for each event. Most partners include this parameter.
req_cost_range_discounts Returns cost range discounts
req_cost_range_best_value_offer Returns the offer with the highest percentage saving. This is the most commonly used offer cost range.
req_cost_range_details Returns a list of unique ticket types and price bands and their cost ranges across all performances.
req_cost_range_max_saving_offer Returns the offer with the highest absolute saving.
req_cost_range_min_cost_offer Returns the offer with the lowest cost.
req_cost_range_top_price_offer Returns the offer with the highest cost. This is the least used offer cost range.
req_cost_range_no_singles_data This returns another cost range object that excludes availability with only 1 consecutive seat available. The prices in this cost range will therefore be the same or higher than the outer cost range. It has the same structure as the main cost range (so if you want to see the “best value offer” in the no singles data, you need to add req_cost_range_best_value_offer and you will see this data in both cost ranges).

Response

Example response

{
  "results": {
    "has_perf_names": true,
    "paging_status": {
      "page_length": 10,
      "page_number": 0,
      "pages_remaining": 10,
      "results_remaining": 94,
      "total_unpaged_results": 104
    },
    "performance": [
      {
        "date_desc": "Thu, 9th March 2017",
        "event_id": "6IF",
        "has_pool_seats": true,
        "is_ghost": false,
        "is_limited": false,
        "iso8601_date_and_time": "2017-03-09T19:30:00Z",
        "perf_id": "6IF-A94",
        "running_time": 120,
        "time_desc": "7.30 PM"
      },
      {
        "date_desc": "Fri, 10th March 2017",
        "event_id": "6IF",
        "has_pool_seats": true,
        "is_ghost": false,
        "is_limited": false,
        "iso8601_date_and_time": "2017-03-10T19:30:00Z",
        "perf_id": "6IF-A95",
        "running_time": 120,
        "time_desc": "7.30 PM"
      },
      {
        "date_desc": "Sun, 12th March 2017",
        "event_id": "6IF",
        "has_pool_seats": true,
        "is_ghost": false,
        "is_limited": false,
        "iso8601_date_and_time": "2017-03-12T19:30:00Z",
        "perf_id": "6IF-A97",
        "running_time": 120,
        "time_desc": "7.30 PM"
      },
      {
        "date_desc": "Mon, 13th March 2017",
        "event_id": "6IF",
        "has_pool_seats": true,
        "is_ghost": false,
        "is_limited": false,
        "iso8601_date_and_time": "2017-03-13T19:30:00Z",
        "perf_id": "6IF-A98",
        "running_time": 120,
        "time_desc": "7.30 PM"
      },
      {
        "date_desc": "Tue, 14th March 2017",
        "event_id": "6IF",
        "has_pool_seats": true,
        "is_ghost": false,
        "is_limited": false,
        "iso8601_date_and_time": "2017-03-14T19:30:00Z",
        "perf_id": "6IF-A99",
        "perf_name": "Including back stage pass",
        "running_time": 120,
        "time_desc": "7.30 PM"
      },
      {
        "date_desc": "Wed, 15th March 2017",
        "event_id": "6IF",
        "has_pool_seats": true,
        "is_ghost": false,
        "is_limited": false,
        "iso8601_date_and_time": "2017-03-15T19:30:00Z",
        "perf_id": "6IF-A9A",
        "running_time": 120,
        "time_desc": "7.30 PM"
      },
      {
        "date_desc": "Thu, 16th March 2017",
        "event_id": "6IF",
        "has_pool_seats": true,
        "is_ghost": false,
        "is_limited": false,
        "iso8601_date_and_time": "2017-03-16T19:30:00Z",
        "perf_id": "6IF-A9B",
        "running_time": 120,
        "time_desc": "7.30 PM"
      },
      {
        "date_desc": "Fri, 17th March 2017",
        "event_id": "6IF",
        "has_pool_seats": true,
        "is_ghost": false,
        "is_limited": false,
        "iso8601_date_and_time": "2017-03-17T19:30:00Z",
        "perf_id": "6IF-A9C",
        "running_time": 120,
        "time_desc": "7.30 PM"
      },
      {
        "date_desc": "Sun, 19th March 2017",
        "event_id": "6IF",
        "has_pool_seats": true,
        "is_ghost": false,
        "is_limited": false,
        "iso8601_date_and_time": "2017-03-19T19:30:00Z",
        "perf_id": "6IF-A9E",
        "running_time": 120,
        "time_desc": "7.30 PM"
      },
      {
        "date_desc": "Mon, 20th March 2017",
        "event_id": "6IF",
        "has_pool_seats": true,
        "is_ghost": false,
        "is_limited": false,
        "iso8601_date_and_time": "2017-03-20T19:30:00Z",
        "perf_id": "6IF-A9F",
        "running_time": 120,
        "time_desc": "7.30 PM"
      }
    ]
  }
}
from pyticketswitch.performance import Performance

[
    Performance(
        id='6IF-B0O',
        event_id='6IF',
        date_time=datetime.datetime(2017, 5, 4, 19, 30, tzinfo=tzoffset(None, 3600)),
        date_description='Thu, 4th May 2017',
        time_description='7.30 PM',
        has_pool_seats=True,
        is_limited=False,
        no_singles_cost_range=None,
        is_ghost=False,
        running_time=120,
    ),
    Performance(
        id='6IF-B0P',
        event_id='6IF',
        date_time=datetime.datetime(2017, 5, 5, 19, 30, tzinfo=tzoffset(None, 3600)),
        date_description='Fri, 5th May 2017',
        time_description='7.30 PM',
        has_pool_seats=True,
        is_limited=False,
        is_ghost=False,
        running_time=120,
    ),
    Performance(
        id='6IF-B0R',
        event_id='6IF',
        date_time=datetime.datetime(2017, 5, 7, 19, 30, tzinfo=tzoffset(None, 3600)),
        date_description='Sun, 7th May 2017',
        time_description='7.30 PM',
        has_pool_seats=True,
        is_limited=False,
        is_ghost=False,
        running_time=120,
    ),
    Performance(
        id='6IF-B0S',
        event_id='6IF',
        date_time=datetime.datetime(2017, 5, 8, 19, 30, tzinfo=tzoffset(None, 3600)),
        date_description='Mon, 8th May 2017',
        time_description='7.30 PM',
        has_pool_seats=True,
        is_limited=False,
        is_ghost=False,
        running_time=120,
    ),
    Performance(
        id='6IF-B0T',
        event_id='6IF',
        date_time=datetime.datetime(2017, 5, 9, 19, 30, tzinfo=tzoffset(None, 3600)),
        date_description='Tue, 9th May 2017',
        time_description='7.30 PM',
        has_pool_seats=True,
        is_limited=False,
        is_ghost=False,
        running_time=120,
    ),
    Performance(
        id='6IF-B0U',
        event_id='6IF',
        date_time=datetime.datetime(2017, 5, 10, 19, 30, tzinfo=tzoffset(None, 3600)),
        date_description='Wed, 10th May 2017',
        time_description='7.30 PM',
        has_pool_seats=True,
        is_limited=False,
        is_ghost=False,
        running_time=120,
    ),
    Performance(
        id='6IF-B0V',
        event_id='6IF',
        date_time=datetime.datetime(2017, 5, 11, 19, 30, tzinfo=tzoffset(None, 3600)),
        date_description='Thu, 11th May 2017',
        time_description='7.30 PM',
        has_pool_seats=True,
        is_limited=False,
        is_ghost=False,
        running_time=120,
    ),
    Performance(
        id='6IF-B0W',
        event_id='6IF',
        date_time=datetime.datetime(2017, 5, 12, 19, 30, tzinfo=tzoffset(None, 3600)),
        date_description='Fri, 12th May 2017',
        time_description='7.30 PM',
        has_pool_seats=True,
        is_limited=False,
        is_ghost=False,
        running_time=120,
    ),
    Performance(
        id='6IF-B0Y',
        event_id='6IF',
        date_time=datetime.datetime(2017, 5, 14, 19, 30, tzinfo=tzoffset(None, 3600)),
        date_description='Sun, 14th May 2017',
        time_description='7.30 PM',
        has_pool_seats=True,
        is_limited=False,
        is_ghost=False,
        running_time=120,
    ),
    Performance(
        id='6IF-B0Z',
        event_id='6IF',
        date_time=datetime.datetime(2017, 5, 15, 19, 30, tzinfo=tzoffset(None, 3600)),
        date_description='Mon, 15th May 2017',
        time_description='7.30 PM',
        has_pool_seats=True,
        is_limited=False,
        is_ghost=False,
        running_time=120,
    ),
    Performance(
        id='6IF-B10',
        event_id='6IF',
        date_time=datetime.datetime(2017, 5, 16, 19, 30, tzinfo=tzoffset(None, 3600)),
        date_description='Tue, 16th May 2017',
        time_description='7.30 PM',
        has_pool_seats=True,
        is_limited=False,
        is_ghost=False,
        running_time=120,
    )
]

Results

Attribute Description
has_perf_names Whether the performances returned have performance names (human readable descriptions of the performance). Performance names are not always present but must be displayed when they are. Performance names are typically used where performances of an event differ significantly in more than just date and time (sometimes the supplier system will not return the time to us in a structured format but it will instead be included as part of the performance name). An example performance with a performance name is 6IF-A5R.
paging_status Information regarding whether the data has been paged.
performance An array of performance objects, described below.

Paging Status

Attribute Description
page_length The page length used for the response. This will either be the value set with the page_len parameter
page_number The zero-based page number currently displayed.
pages_remaining The number of pages that you need to request after the current page to retrieve all results.
results_remaining The number of results in the remaining pages.
total_unpaged_results The total number of results.

Performance

Attribute Description
date_desc human readable date description
event_id Unique identifier for the event that this performance is an instance of
has_pool_seats Whether this performance has tickets available from the general pool of tickets. This is ignored by most partners.
is_ghost true when this performance is no longer on sale. When you request performances for an event we will only return performances that are on sale (so is_ghost will always be false), however it is possible to request performances by ID for a ghost performance.
is_limited Indicates whether the supply of tickets is known to be extremely limited. This is usually taken to be fewer than four remaining, though not all ticket sources provide this information. Where the information is not available the flag will always be set to false
iso8601_date_and_time ISO 8601 date and time
perf_id Unique identifier for the performance
perf_name A human readable description of the performance. Performance names are not always present but must be displayed when they are. Performance names are typically used where performances of an event differ significantly in more than just date and time (sometimes the supplier system will not return the time to us in a structured format but it will instead be included as part of the performance name). Event ID 6IF includes some performances with names.
running_time The length / duration of the performance in minutes
time_desc A human readable time description
cached_max_seats This should not be used. Earlier versions of the documentation implied that it held a meaningful value for the availability, but this is not true, and the attribute was not always present. If you are using it then you should stop, and switch to cost range data instead if you still want cached availability data. For the time being the value will be one million instead of being absent entirely if the data is not available.
cached_max_seats_is_real A boolean indicating whether the data in the previous variable is actually real or not. Can be used whilst migrating away from using it.

Performances by ID

Definition

GET https://api.ticketswitch.com/f13/performances_by_id.v1?perf_id_list={perfidlist}

This resource is used to return detail for one or more performances by their ID. It returns a dictionary of performances.

If you have a need to request availability for a subset of performances in a guaranteed fast response time then one way to achieve it is to use this call with the req_avail_details parameter - this will return the list of available price bands from Ingresso’s cached data. Note that the cached data can be out of date or not present, and doesn’t return seating data, so we do not recommend this in most cases.

Request

Example request

curl https://api.ticketswitch.com/f13/performances_by_id.v1 \
    -u "demo:demopass" \
    -d "perf_id_list=6IF-B2E,6IF-B2F" \
    --compressed \
    -G
from pyticketswitch import Client


client = Client('demo', 'demopass')
performances, meta = client.get_performances(['6IF-B2E', '6IF-B2F'])
Parameter Description
perf_id_list A comma separated list of performance IDs e.g. 6IF-A5R for a single performance; 6IF-A5R,6IF-A5S for multiple performances.

These parameters can be passed in to request additional data for each performance, and are described in more detail in the extra parameters section below:

Parameter Description
req_avail_details Returns availability details - a cached list of unique ticket types and price bands available for this performance. This parameter is not commonly used.
req_cost_range Returns cost ranges - a from price and offer detail for each event. Most partners include this parameter.
req_cost_range_best_value_offer Returns the offer with the highest percentage saving. This is the most commonly used offer cost range.
req_cost_range_details Returns a list of unique ticket types and price bands and their cost ranges across all performances.
req_cost_range_max_saving_offer Returns the offer with the highest absolute saving.
req_cost_range_min_cost_offer Returns the offer with the lowest cost.
req_cost_range_top_price_offer Returns the offer with the highest cost. This is the least used offer cost range.
req_cost_range_no_singles_data This returns another cost range object that excludes availability with only 1 consecutive seat available. The prices in this cost range will therefore be the same or higher than the outer cost range. It has the same structure as the main cost range (so if you want to see the “best value offer” in the no singles data, you need to add req_cost_range_best_value_offer and you will see this data in both cost ranges).

Response

Example response

{
  "performances_by_id": {
    "6IF-B2E": {
      "date_desc": "Wed, 5th July 2017",
      "event_id": "6IF",
      "has_pool_seats": true,
      "is_ghost": false,
      "is_limited": false,
      "iso8601_date_and_time": "2017-07-05T19:30:00+01:00",
      "perf_id": "6IF-B2E",
      "running_time": 120,
      "time_desc": "7.30 PM"
    },
    "6IF-B2F": {
      "date_desc": "Thu, 6th July 2017",
      "event_id": "6IF",
      "has_pool_seats": true,
      "is_ghost": false,
      "is_limited": false,
      "iso8601_date_and_time": "2017-07-06T19:30:00+01:00",
      "perf_id": "6IF-B2F",
      "running_time": 120,
      "time_desc": "7.30 PM"
    }
  }
}
from pyticketswitch.performance import Performance

{
    '6IF-B2E': Performance(
        id='6IF-B2E',
        event_id='6IF',
        date_time=datetime.datetime(2017, 7, 5, 19, 30, tzinfo=tzoffset(None, 3600)),
        date_description='Wed, 5th July 2017',
        time_description='7.30 PM',
        has_pool_seats=True,
        is_limited=False,
        is_ghost=False,
        running_time=120,
    ),
    '6IF-B2F': Performance(
        id='6IF-B2F',
        event_id='6IF',
        date_time=datetime.datetime(2017, 7, 6, 19, 30, tzinfo=tzoffset(None, 3600)),
        date_description='Thu, 6th July 2017',
        time_description='7.30 PM',
        has_pool_seats=True,
        is_limited=False,
        is_ghost=False,
        running_time=120,
    )
}
Attribute Description
date_desc human readable date description
event_id Unique identifier for the event that this performance is an instance of
has_pool_seats Whether this performance has tickets available from the general pool of tickets. This is ignored by most partners.
is_ghost true when this performance is no longer on sale. When you request performances for an event we will only return performances that are on sale (so is_ghost will always be false), however it is possible to request performances by ID for a ghost performance.
is_limited Indicates whether the supply of tickets is known to be extremely limited. This is usually taken to be fewer than four remaining, though not all ticket sources provide this information. Where the information is not available the flag will always be set to false
iso8601_date_and_time ISO 8601 date and time
perf_id Unique identifier for the performance
perf_name A human readable description of the performance. Performance names are not always present but must be displayed when they are. Performance names are typically used where performances of an event differ significantly in more than just date and time (sometimes the supplier system will not return the time to us in a structured format but it will instead be included as part of the performance name). Event ID 6IF includes some performances with names.
running_time The length / duration of the performance in minutes
time_desc human readable time description

— Extra parameters —

There are several additional parameters described below that can be provided to return additional data for each performance.

These additional parameters require extra processing to retrieve the requested data, which will slow down the resource, sometimes substantially. They should therefore only be used where necessary.

Cost ranges

Cost ranges are a cached summary of the pricing that has been seen for your username. They are used to retrieve the minimum (or “from”) price for the performance, along with detail of any offers or discounts. They allow you to display a from price and whether there is an offer for each performance, so most partners request cost ranges.

Cost ranges are generated from availability requests made either by end-users or by scheduled processes that Ingresso use to update cost range data. You should not attempt to make multiple availability requests in order to keep this data up to date - please contact us instead to discuss options. Cost ranges are only ever returned as part of a parent object.

Request

Example request

curl https://api.ticketswitch.com/f13/performances_by_id.v1 \
    -u "demo:demopass" \
    -d "perf_id_list=6L9-M5P" \
    -d "req_cost_range" \
    -d "req_cost_range_best_value_offer" \
    -d "req_cost_range_max_saving_offer" \
    -d "req_cost_range_min_cost_offer" \
    -d "req_cost_range_top_price_offer" \
    -d "req_cost_range_no_singles_data" \
    --compressed \
    -G
from pyticketswitch import Client


client = Client('demo', 'demopass')
performances, meta = client.get_performances(
    performance_ids=['6L9-M4C'],
    cost_range=True,
    best_value_offer=True,
    max_saving_offer=True,
    min_cost_offer=True,
    top_price_offer=True,
    no_singles_data=True,
)

On its own, req_cost_range will add min and max prices only, however by adding one of the other 5 parameters below you can receive additional data (multiple parameters are provided because there can be multiple definitions of the “best” offer). Most API users request cost ranges.

Parameter Description
req_cost_range Returns cost ranges for each performance.
req_cost_range_best_value_offer Returns the offer with the highest percentage saving. This is the most commonly used offer cost range.
req_cost_range_max_saving_offer Returns the offer with the highest absolute saving.
req_cost_range_min_cost_offer Returns the offer with the lowest cost.
req_cost_range_top_price_offer Returns the offer with the highest cost. This is the least used offer cost range.
req_cost_range_no_singles_data This returns another cost range object that excludes availability with only 1 consecutive seat available. The prices in this cost range will therefore be the same or higher than the outer cost range. It has the same structure as the main cost range (so if you want to see the “best value offer” in the no singles data, you need to add req_cost_range_best_value_offer and you will see this data in both cost ranges).

Response

Example response

{
  "currency_details": {
    "usd": {
      "currency_code": "usd",
      "currency_factor": 100,
      "currency_number": 840,
      "currency_places": 2,
      "currency_post_symbol": "",
      "currency_pre_symbol": "$"
    }
  },
  "performances_by_id": {
    "6L9-M2R": {
      "cost_range": {
        "best_value_offer": {
          "absolute_saving": 9,
          "full_seatprice": 75,
          "full_surcharge": 5,
          "offer_seatprice": 68,
          "offer_surcharge": 3,
          "percentage_saving": 11
        },
        "max_saving_offer": {
          "absolute_saving": 9,
          "full_seatprice": 75,
          "full_surcharge": 5,
          "offer_seatprice": 68,
          "offer_surcharge": 3,
          "percentage_saving": 11
        },
        "max_seatprice": 68,
        "max_surcharge": 3,
        "min_cost_offer": {
          "absolute_saving": 9,
          "full_seatprice": 75,
          "full_surcharge": 5,
          "offer_seatprice": 68,
          "offer_surcharge": 3,
          "percentage_saving": 11
        },
        "min_seatprice": 68,
        "min_surcharge": 3,
        "no_singles_cost_range": {
          "best_value_offer": {
            "absolute_saving": 9,
            "full_seatprice": 75,
            "full_surcharge": 5,
            "offer_seatprice": 68,
            "offer_surcharge": 3,
            "percentage_saving": 11
          },
          "max_saving_offer": {
            "absolute_saving": 9,
            "full_seatprice": 75,
            "full_surcharge": 5,
            "offer_seatprice": 68,
            "offer_surcharge": 3,
            "percentage_saving": 11
          },
          "max_seatprice": 68,
          "max_surcharge": 3,
          "min_cost_offer": {
            "absolute_saving": 9,
            "full_seatprice": 75,
            "full_surcharge": 5,
            "offer_seatprice": 68,
            "offer_surcharge": 3,
            "percentage_saving": 11
          },
          "min_seatprice": 68,
          "min_surcharge": 3,
          "range_currency_code": "usd",
          "top_price_offer": {
            "absolute_saving": 9,
            "full_seatprice": 75,
            "full_surcharge": 5,
            "offer_seatprice": 68,
            "offer_surcharge": 3,
            "percentage_saving": 11
          },
          "valid_quantities": [
            1,
            2,
            3,
            4
          ]
        },
        "range_currency_code": "usd",
        "top_price_offer": {
          "absolute_saving": 9,
          "full_seatprice": 75,
          "full_surcharge": 5,
          "offer_seatprice": 68,
          "offer_surcharge": 3,
          "percentage_saving": 11
        },
        "valid_quantities": [
          1,
          2,
          3,
          4
        ]
      },
      "date_desc": "Wed, 5th April 2017",
      "event_id": "6L9",
      "has_pool_seats": true,
      "is_ghost": false,
      "is_limited": false,
      "iso8601_date_and_time": "2017-04-05T22:30:00-07:00",
      "perf_id": "6L9-M2R",
      "running_time": 120,
      "time_desc": "10.30 PM"
    }
  }
}

FIXME: no cost ranges on this performance

from pyticketswitch.performance import Performance

{
    '6L9-M2R': Performance(
        id='6L9-M2R',
        event_id='6L9',
        date_time=datetime.datetime(2017, 4, 5, 22, 30, tzinfo=tzoffset(None, -25200)),
        date_description='Wed, 5th April 2017',
        time_description='10.30 PM',
        has_pool_seats=False,
        is_limited=False,
        cost_range=None,
        no_singles_cost_range=None,
        is_ghost=True,
        name=None,
        running_time=None,
        availability_details=[

        ],
    )
}

Each performance returned includes a cost_range object with the following attributes:

Attribute Description
best_value_offer The offer with the highest percentage saving. This is the most commonly used offer cost range.
max_saving_offer The offer with the highest absolute saving.
max_seatprice The per-ticket face value for the highest price (seatprice + surcharge)
max_surcharge The per-ticket booking fee for the highest price (seatprice + surcharge)
min_cost_offer The offer with the lowest cost.
min_seatprice The per-ticket face value for the lowest price (seatprice + surcharge)
min_surcharge The per-ticket booking fee for the lowest price (seatprice + surcharge)
no_singles_cost_range This returns another cost range object that excludes availability with only one consecutive seat available. The prices in this cost range will therefore be the same as or higher than the outer cost range.
range_currency_code The currency code for the cost range - further detail for the currency can be found in the currency_details object, described below.
top_price_offer The offer with the highest cost. This is the least used offer cost range.
valid_quantities An array of ticket quantities with availability.

The offer objects contain the following attributes:

Attribute Description
absolute_saving Defined as (full_seatprice + full_surcharge) - (offer_seatprice + offer_surcharge).
full_seatprice The non-offer per-ticket face value.
full_surcharge The non-offer per-ticket booking fee.
offer_seatprice The offer per-ticket face value.
offer_surcharge The offer per-ticket booking fee.
percentage_saving Defined as absolute_saving / (full_seatprice + full_surcharge) * 100.

The outer object includes a currency_details object containing one currency object (indexed on the currency code) for every currency referenced in the JSON response. Each currency has the following attributes:

Attribute Description
currency_code ISO 4217 three letter code
currency_factor Multiply by this number to get values in the base unit (e.g. multiplying $47.11 by the currency_factor will give 4711 cents)
currency_number ISO 4217 numeric identifier
currency_places The number of decimal places to display (eg 45.5 usd should be displayed as 45.50)
currency_post_symbol A symbol to display at the end of the price
currency_pre_symbol A symbol to display in front of the price

Availability detail

Availability details are a cached list of the price bands for each performance. They are cached from previous availability requests made via your username. This data can be useful for example if you wish to display a separate page with pricing detail for all price bands on sale.

Availability details are generated from availability requests made either by end-users or by scheduled processes that Ingresso use to update this data. You should not attempt to make multiple availability requests in order to keep this data up to date - please contact us instead to discuss options

Request

Example request

curl https://api.ticketswitch.com/f13/performances_by_id.v1 \
    -u "demo:demopass" \
    -d "perf_id_list=6L9-M2R" \
    -d "req_avail_details" \
    --compressed \
    -G
from pyticketickswitch import client

client = Client('demo', 'demopass')
performances, meta = client.get_performances(['6L9-M2R'], availability=True)
Parameter Description
req_avail_details Returns a list of unique ticket types and price bands that are available for this performance. This parameter is not commonly used.

Response

Example Response

{
  "currency_details": {
    "usd": {
      "currency_code": "usd",
      "currency_factor": 100,
      "currency_number": 840,
      "currency_places": 2,
      "currency_post_symbol": "",
      "currency_pre_symbol": "$"
    }
  },
  "performances_by_id": {
    "6L9-M2R": {
      "avail_details": {
        "ticket_type": [
          {
            "price_band": [
              {
                "avail_detail": [
                  {
                    "absolute_saving": 9,
                    "avail_currency_code": "usd",
                    "cached_number_available": 4,
                    "full_seatprice": 75,
                    "full_surcharge": 5,
                    "percentage_saving": 11,
                    "seatprice": 68,
                    "surcharge": 3,
                    "valid_quantities": [
                      1,
                      2,
                      3,
                      4
                    ]
                  }
                ],
                "price_band_code": "A",
                "price_band_desc": ""
              }
            ],
            "ticket_type_code": "PREF",
            "ticket_type_desc": "Preferred seating"
          }
        ]
      },
      "date_desc": "Wed, 5th April 2017",
      "event_id": "6L9",
      "has_pool_seats": true,
      "is_ghost": false,
      "is_limited": false,
      "iso8601_date_and_time": "2017-04-05T22:30:00-07:00",
      "perf_id": "6L9-M2R",
      "running_time": 120,
      "time_desc": "10.30 PM"
    }
  }
}
{
    '6IF-A8K': pyticketswitch.Performance(
        id='6IF-A8K',
        availabilty_details=[
            pyticketswitch.AvailabilityDetails(
                ticket_type='BALCONY',
                ticket_type_description='Balcony',
                price_band='A',
                price_band_description='',
                seatprice=47.0,
                surcharge=0.0,
                currency=pyticketswitch.Currency(
                    code='gbp',
                ),
                valid_quantities=[2, 3, 4, 5, 6, 7],
            ),
            pyticketswitch.AvailabilityDetails(
                ticket_type='CIRCLE',
                ticket_type_description='Upper circle',
                price_band='A',
                price_band_description='',
                seatprice=35.0,
                surcharge=0.0,
                currency=pyticketswitch.Currency(
                    code='gbp',
                ),
                valid_quantities=[2, 3, 4, 5, 6, 7],
            ),
            pyticketswitch.AvailabilityDetails(
                ticket_type='CIRCLE',
                ticket_type_description='Upper circle',
                price_band='B',
                price_band_description='',
                seatprice=30.0,
                surcharge=0.0,
                currency=pyticketswitch.Currency(
                    code='gbp',
                ),
                valid_quantities=[2, 3, 4, 5, 6, 7],
            ),
            pyticketswitch.AvailabilityDetails(
                ticket_type='CIRCLE',
                ticket_type_description='Upper circle',
                price_band='C',
                price_band_description='',
                seatprice=25.0,
                surcharge=0.0,
                currency=pyticketswitch.Currency(
                    code='gbp',
                ),
                valid_quantities=[2, 3, 4, 5, 6, 7],
            ),
            pyticketswitch.AvailabilityDetails(
                ticket_type='STALLS',
                ticket_type_description='Stalls',
                price_band='A',
                price_band_description='',
                seatprice=21.0,
                surcharge=0.0,
                currency=pyticketswitch.Currency(
                    code='gbp',
                ),
                valid_quantities=[2, 3, 4, 5, 6, 7],
            ),
            pyticketswitch.AvailabilityDetails(
                ticket_type='STALLS',
                ticket_type_description='Stalls',
                price_band='B',
                price_band_description='',
                seatprice=18.0,
                surcharge=0.0,
                currency=pyticketswitch.Currency(
                    code='gbp',
                ),
                valid_quantities=[2, 3, 4, 5, 6, 7],
            ),
        ],
    )
}

Ticket types describe a part of house or location within the venue.

Attribute Description
price_band A list of price bands, object described below.
ticket_type_code The identifier of the ticket type, this can be used later in the trolley or reserve resource.
ticket_type_desc A human readable description of the price band if applicable.

Price bands describe the different levels of pricing that are available within a ticket type.

Attribute Description
avail_details A list of the prices in this price band and when they are available.
price_band_code The identifier of the price band, this can be used later in the trolley or reserve resource.
price_band_desc A human readable description of the price band if applicable.

The avail detail indicates what prices we have seen for this performance.

Attribute Description
absolute_saving Defined as (full_seatprice + full_surcharge) - (seatprice + surcharge)
avail_currency_code The currency code for the price - further detail for the currency can be found in the currency_details object, described below.
cached_number_available The maximum number of consecutive tickets available.
full_seatprice The per-ticket face value for the non-discounted ticket price.
full_surcharge The per-ticket booking fee for the non-discounted ticket price.
percentage_saving Defined as absolute_saving / (full_seatprice + full_surcharge) * 100
seatprice The per-ticket face value.
surcharge The per-ticket booking fee.
valid_quantities An array of available quantities we have seen for this price band.

The outer object includes a currency_details object containing one currency object (indexed on the currency code) for every currency referenced in the JSON response. Each currency has the following attributes:

Attribute Description
currency_code ISO 4217 three letter code
currency_factor Multiply by this number to get values in the base unit (e.g. multiplying $47.11 by the currency_factor will give 4711 cents)
currency_number ISO 4217 numeric identifier
currency_places The number of decimal places to display (eg 45.5 usd should be displayed as 45.50)
currency_post_symbol A symbol to display at the end of the price
currency_pre_symbol A symbol to display in front of the price

Months

GET https://api.ticketswitch.com/f13/months.v1?event_id={eventid}

This resource gives a summary of the availability across calendar months

months is provided for those who wish to display month-level summary data; for example listing the available months in tabs above a calendar. This resource can remove the need to summarise performance-level data in your application.

It is an optional resource that not all partners choose to use.

Example request

curl https://api.ticketswitch.com/f13/months.v1 \
    -u "demo:demopass" \
    -d "event_id=6IF" \
    --compressed \
    -G
from pyticketswitch import Client

client = Client('demo', 'demopass')
client.get_months('6IF')

Request

Parameter Description
event_id Identifier of the event to summarise

These parameters can be passed in to request additional data for each performance, and are described in more detail in the extra parameters section above for performances.

Parameter Description
req_avail_details Returns availability details - a cached list of unique ticket types and price bands available for this event across all performances in the month. This parameter is not commonly used.
req_cost_range Returns cost ranges - a from price and offer detail for each event. Most partners include this parameter.
req_cost_range_best_value_offer Returns the offer with the highest percentage saving. This is the most commonly used offer cost range.
req_cost_range_details Returns a list of unique ticket types and price bands and their cost ranges across all performances.
req_cost_range_max_saving_offer Returns the offer with the highest absolute saving.
req_cost_range_min_cost_offer Returns the offer with the lowest cost.
req_cost_range_top_price_offer Returns the offer with the highest cost. This is the least used offer cost range.
req_cost_range_no_singles_data This returns another cost range object that excludes availability with only 1 consecutive seat available. The prices in this cost range will therefore be the same or higher than the outer cost range. It has the same structure as the main cost range (so if you want to see the “best value offer” in the no singles data, you need to add req_cost_range_best_value_offer and you will see this data in both cost ranges).

Example Response

{
  "results": {
    "month": [
      {
        "month": "dec",
        "month_dates_bitmask": 1065254912,
        "month_desc": "December",
        "month_weekdays_bitmask": 63,
        "year": 2016
      },
      {
        "month": "jan",
        "month_dates_bitmask": 2012209087,
        "month_desc": "January",
        "month_weekdays_bitmask": 63,
        "year": 2017
      },
      {
        "month": "feb",
        "month_dates_bitmask": 251526135,
        "month_desc": "February",
        "month_weekdays_bitmask": 63,
        "year": 2017
      },
      {
        "month": "mar",
        "month_dates_bitmask": 2130574327,
        "month_desc": "March",
        "month_weekdays_bitmask": 63,
        "year": 2017
      },
      {
        "month": "apr",
        "month_dates_bitmask": 16254,
        "month_desc": "April",
        "month_weekdays_bitmask": 63,
        "year": 2017
      }
    ]
  }
}
from pyticketswitch.month import Month

[
    Month(
        month=5,
        year=2017,
        description='May',
        _dates_bitmask=2079846360,
        _weekday_bitmask=63,
    ),
    Month(
        month=6,
        year=2017,
        description='June',
        _dates_bitmask=1065287163,
        _weekday_bitmask=63,
    ),
    Month(
        month=7,
        year=2017,
        description='July',
        _dates_bitmask=1876934526,
        _weekday_bitmask=63,
    ),
    Month(
        month=8,
        year=2017,
        description='August',
        _dates_bitmask=2113665007,
        _weekday_bitmask=63,
    )
]

Response

Attribute Description
month Three-character code for the month.
month_dates_bitmask Indicates which dates in the month have valid performances.
month_desc Full month name.
month_weekdays_bitmask Indicates which days of the week have valid performances for the month - see the example in the bitmask fields explanation.
year The year.

Availability

Definition

GET https://api.ticketswitch.com/f13/availability.v1?perf_id={performanceid}

availability lists the tickets that are currently available for a performance. In most cases the availability provided is in real time (although we do sometimes cache availability) and represents the tickets available at the time the request was made. There is therefore no guarantee that the tickets will still be available to purchase at some future time. Tickets are only guaranteed to be held after you reserve tickets.

We have a single availability resource that will return best available tickets by default. This resource is described first and is important to read. We then describe optional parameters that can be passed to request individual seats, example seats, commission, and discounts.

You should only send availability requests as a direct result of customers requesting availability. You should not automatically request availability to populate caches. Performances with availability detail is provided for this type of use case. If this doesn’t fit what you are trying to do contact us

Important: Ingresso offer an interactive seat map widget called Feather that can be embedded in your website, saving you development effort. This is an alternative to requesting availability via the API and displaying it yourself.

Availability

Request

Example request

curl https://api.ticketswitch.com/f13/availability.v1 \
    -u "demo:demopass" \
    -d "perf_id=6IF-B5P" \
    --compressed \
    -G
from pyticketswitch import Client

client = Client('demo', 'demopass')
ticket_types, meta = client.get_availability('6IF-B5P')
Attribute Description
perf_id The identifier of the performance that you wish to request availability for.
no_of_seats Optional. The number of tickets the customer would like. If this is specified then seated availability will only be shown for price bands with at least that many contiguous seats available.
promo_code Optional. If the supplier supports a promo code this can be specified to unlock discounted pricing. This feature is not commonly used with partners.

These parameters can be included to request additional data:

Parameter Description
add_discounts discounts
add_example_seats Include to retrieve example seats. These can be displayed alongside the ticket options when presenting availability to customers. The inclusion of this parameter does not guarantee that example seats data will be returned - this also depends on (a) whether the event is seated and (b) whether the supplier system returns seats at availability time.
add_seat_blocks Include to retrieve individual seats (if, for example, you wish to offer seat selection to your customer). The inclusion of this parameter does not guarantee that individual seat data will be returned - this also depends on (a) whether the event is seated and (b) whether the supplier system supports seat selection.
req_predicted_commission Include to retrieve commission data. For most partners this will include predicted_user_commission only (the predicted amount you earn per ticket). Some partners will also see predicted_gross_commission, which is the total commission available to be shared between Ingresso and our partner. By default you will see predicted_user_commission only - if you think you need to see predicted_gross_commission as well then please get in touch.

Response

Example response

{
  "availability": {
    "ticket_type": [
      {
        "price_band": [
          {
            "absolute_saving": 0,
            "allows_leaving_single_seats": "always",
            "discount_code": "",
            "discount_desc": "",
            "is_offer": false,
            "non_offer_sale_seatprice": 35,
            "non_offer_sale_surcharge": 4,
            "number_available": 6,
            "percentage_saving": 0,
            "price_band_code": "A/pool",
            "sale_seatprice": 35,
            "sale_surcharge": 4
          },
          {
            "absolute_saving": 0,
            "allows_leaving_single_seats": "always",
            "discount_code": "",
            "discount_desc": "",
            "is_offer": false,
            "non_offer_sale_seatprice": 30,
            "non_offer_sale_surcharge": 4,
            "number_available": 6,
            "percentage_saving": 0,
            "price_band_code": "B/pool",
            "sale_seatprice": 30,
            "sale_surcharge": 4
          },
          {
            "absolute_saving": 0,
            "allows_leaving_single_seats": "always",
            "discount_code": "",
            "discount_desc": "",
            "is_offer": false,
            "non_offer_sale_seatprice": 25,
            "non_offer_sale_surcharge": 4,
            "number_available": 6,
            "percentage_saving": 0,
            "price_band_code": "C/pool",
            "sale_seatprice": 25,
            "sale_surcharge": 4
          }
        ],
        "ticket_type_code": "CIRCLE",
        "ticket_type_desc": "Upper circle"
      },
      {
        "price_band": [
          {
            "absolute_saving": 0,
            "allows_leaving_single_seats": "always",
            "discount_code": "",
            "discount_desc": "",
            "is_offer": false,
            "non_offer_sale_seatprice": 21,
            "non_offer_sale_surcharge": 3,
            "number_available": 6,
            "percentage_saving": 0,
            "price_band_code": "A/pool",
            "sale_seatprice": 21,
            "sale_surcharge": 3
          },
          {
            "absolute_saving": 0,
            "allows_leaving_single_seats": "always",
            "discount_code": "",
            "discount_desc": "",
            "is_offer": false,
            "non_offer_sale_seatprice": 18,
            "non_offer_sale_surcharge": 3,
            "number_available": 3,
            "percentage_saving": 0,
            "price_band_code": "B/pool",
            "sale_seatprice": 18,
            "sale_surcharge": 3
          }
        ],
        "ticket_type_code": "STALLS",
        "ticket_type_desc": "Stalls"
      },
      {
        "price_band": [
          {
            "absolute_saving": 0,
            "allows_leaving_single_seats": "always",
            "discount_code": "",
            "discount_desc": "",
            "is_offer": false,
            "non_offer_sale_seatprice": 47,
            "non_offer_sale_surcharge": 5,
            "number_available": 6,
            "percentage_saving": 0,
            "price_band_code": "A/pool",
            "sale_seatprice": 47,
            "sale_surcharge": 5
          }
        ],
        "ticket_type_code": "BALCONY",
        "ticket_type_desc": "Balcony"
      }
    ]
  },
  "backend_is_broken": false,
  "backend_is_down": false,
  "backend_throttle_failed": false,
  "contiguous_seat_selection_only": true,
  "currency_code": "gbp",
  "currency_details": {
    "gbp": {
      "currency_code": "gbp",
      "currency_factor": 100,
      "currency_number": 826,
      "currency_places": 2,
      "currency_post_symbol": "",
      "currency_pre_symbol": "£"
    }
  },
  "max_bundle_size": 1,
  "valid_quantities": [
    1,
    2,
    3,
    4,
    5,
    6
  ]
}
from pyticketswitch.price_band import PriceBand
from pyticketswitch.discount import Discount
from pyticketswitch.ticket_type import TicketType

[
    TicketType(
        code='CIRCLE',
        description='Upper circle',
        price_bands=[
            PriceBand(
                code='A/pool',
                allows_leaving_single_seats='always',
                default_discount=Discount(
                    code='',
                    description='',
                    price_band_code='A/pool',
                    is_offer=False,
                    seatprice=35.0,
                    surcharge=4.0,
                    non_offer_seatprice=35.0,
                    non_offer_surcharge=4.0,
                    availability=6,
                    percentage_saving=0,
                    absolute_saving=0.0,
                ),
                example_seats_are_real=True,
            ),
            PriceBand(
                code='B/pool',
                allows_leaving_single_seats='always',
                default_discount=Discount(
                    code='',
                    description='',
                    price_band_code='B/pool',
                    is_offer=False,
                    seatprice=30.0,
                    surcharge=4.0,
                    non_offer_seatprice=30.0,
                    non_offer_surcharge=4.0,
                    availability=6,
                    percentage_saving=0,
                    absolute_saving=0.0,
                ),
                example_seats_are_real=True,
            ),
            PriceBand(
                code='C/pool',
                allows_leaving_single_seats='always',
                default_discount=Discount(
                    code='',
                    description='',
                    price_band_code='C/pool',
                    is_offer=False,
                    seatprice=25.0,
                    surcharge=4.0,
                    non_offer_seatprice=25.0,
                    non_offer_surcharge=4.0,
                    availability=6,
                    percentage_saving=0,
                    absolute_saving=0.0,
                ),
                example_seats_are_real=True,
            )
        ],
    ),
    TicketType(
        code='STALLS',
        description='Stalls',
        price_bands=[
            PriceBand(
                code='A/pool',
                allows_leaving_single_seats='always',
                default_discount=Discount(
                    code='',
                    description='',
                    price_band_code='A/pool',
                    is_offer=False,
                    seatprice=21.0,
                    surcharge=3.0,
                    non_offer_seatprice=21.0,
                    non_offer_surcharge=3.0,
                    availability=6,
                    percentage_saving=0,
                    absolute_saving=0.0,
                ),
                example_seats_are_real=True,
            ),
            PriceBand(
                code='B/pool',
                allows_leaving_single_seats='always',
                default_discount=Discount(
                    code='',
                    description='',
                    price_band_code='B/pool',
                    is_offer=False,
                    seatprice=18.0,
                    surcharge=3.0,
                    non_offer_seatprice=18.0,
                    non_offer_surcharge=3.0,
                    availability=3,
                    percentage_saving=0,
                    absolute_saving=0.0,
                ),
                example_seats_are_real=True,
            )
        ],
    ),
    TicketType(
        code='BALCONY',
        description='Balcony',
        price_bands=[
            PriceBand(
                code='A/pool',
                allows_leaving_single_seats='always',
                default_discount=Discount(
                    code='',
                    description='',
                    price_band_code='A/pool',
                    is_offer=False,
                    seatprice=47.0,
                    surcharge=5.0,
                    non_offer_seatprice=47.0,
                    non_offer_surcharge=5.0,
                    availability=6,
                    percentage_saving=0,
                    absolute_saving=0.0,
                ),
                example_seats_are_real=True,
            )
        ],
    )
]

Availability is divided into a set of ticket types, and each ticket type is subdivided into price bands. If you request individual seats for a seated event each price band includes seat blocks for the contiguous seats. The structure of the availability data returned is therefore:

Availability Hierarchy

This example response is for best available - following this there is an example response that includes seats.

Top-level attributes:

Attribute Description
availability Contains ticket types, object described below.
backend_is_broken If we see an unexpected error from the supplier system (for example a 500 error) we mark the system as “broken” for a period of time afterwards (the time can vary from nothing to 2 minutes). During this period of time this attribute will be true and we will return empty availability. This is an exceptional circumstance; to check if there is currently a supplier system issue you can check our status page.
backend_is_down When true the supplier system cannot be contacted for some reason, for example they are having technical problems or scheduled maintenance. The response will include empty availability in this case. This is an exceptional circumstance; to check if there is currently a supplier system issue you can check our status page.
backend_throttle_failed We allow a certain number of simultaneous requests to hit a supplier system and queue requests when the limit is reached. When this attribute is true your request has been sitting in our queue for a long time and we have timed out the request. This is an exceptional circumstance.
contiguous_seat_selection_only If you have requested individual seats a value of true indicates that you can only select consecutive seats. false indicates that you can select seats without restriction within a single ticket type and price band. In most cases this will be false. If you would like to allow your customers to select seats without restriction across price bands and ticket types, you need to add multiple orders to a trolley, one order for each price band. However there are currently some restrictions enforced so if you want to do this you will need to contact us first
currency_code The currency code for the availability.
currency_details Further detail for the currency, object described below.
max_bundle_size The maximum number of orders that can be added to a trolley for this event. Useful for buying tickets from different ticket types and price bands. If this isn’t present then there is no max bundle size.
valid_quantities An array of valid quantities.

The currency_details object containing one currency object (indexed on the currency code) for every currency referenced in the JSON response. Each currency has the following attributes:

Attribute Description
currency_code ISO 4217 three letter code
currency_factor Multiply by this number to get values in the base unit (e.g. multiplying $47.11 by the currency_factor will give 4711 cents)
currency_number ISO 4217 numeric identifier
currency_places The number of decimal places to display (eg 45.5 usd should be displayed as 45.50)
currency_post_symbol A symbol to display at the end of the price
currency_pre_symbol A symbol to display in front of the price

Ticket type attributes:

Attribute Description
price_band Object described below.
ticket_type_code The unique identifier for the ticket type. For attractions this can refer to variations such as General Admission or Fast Track, and there is often only only. For seated events this normally refers to a part of house / seating area such as Grand Circle.
ticket_type_desc The description for the ticket type. This should be displayed to the customer (if you are offering seat selection to your customer then you would typically hard-code the description when drawing a seating plan).

Price band attributes:

Attribute Description
absolute_saving Defined as (non_offer_sale_seatprice + non_offer_sale_surcharge) - (sale_seatprice + sale_surcharge)
allows_leaving_single_seats In most cases this is always. When set to never, the supplier ticketing system does not allow us to leave single seats (which are difficult to sell). If you attempt to reserve when leaving a single seat the reserve will fail, so you should prevent your customer from making a selection that leaves a single seat. The other possible value is if_necessary: reservations will succeed if there is no other possible seat selection with the number of desired tickets that would not also leave a single seat (e.g. two tickets are requested and all available seat blocks are of size 3 or smaller).
discount_code The unique identifier of the default discount. Each price band has a default discount, but additional discounts can be requested for a price band with list discounts.
discount_desc The description of the default discount. We recommend to present this text to customers when is_offer is true to describe the offer.
is_offer true if the ticket price is discounted below the full price, i.e. if absolute_saving is greater than zero.
non_offer_sale_seatprice The per-ticket price for full-priced tickets. This will be the face value price when the market has such a concept (for example the London theatre market has this concept, but some New York theatre shows do not). This is the same as the sale_seatprice when the price band is not discounted.
non_offer_sale_surcharge The per-ticket booking fee for full-priced tickets. To determine the total ticket price you must add together the non_offer_sale_seatprice and the non_offer_sale_surcharge.
number_available This is the maximum number of contiguous seats that can be purchased. This applies to best available only - if you are using seat selection and contiguous_seat_selection_only is false it is possible to select above this number.
percentage_saving Defined as absolute_saving / (non_offer_sale_seatprice + non_offer_sale_surcharge) * 100
price_band_code The code for the price band, for example “C/pool”. To uniquely identify a price band you should take the combination of ticket_type_code and price_band_code. The price band code is generally made up of the code from the underlying supplier system, e.g. “C”, followed by a “/” separator then “pool” or “alloc”, indicating whether the price band is taken from the general pool of tickets or is from a ring-fenced allocation. Integrating partners should just work with the full price_band_code, ignoring the constituent parts.
price_band_desc The description for the price band. This will often not be present (not all supplier ticketing systems provide it) but when it is present it should be displayed to the customer.
sale_seatprice The per-ticket price. This will be the face value price when the market has such a concept (for example the London theatre market has this concept, but some New York theatre shows do not). This is the same as the non_offer_sale_seatprice when the price band is not discounted.
sale_surcharge The per-ticket booking fee. To determine the total ticket price you must add together the sale_seatprice and the sale_surcharge.

— Optional Parameters —

There are several additional parameters described below that can be provided to return additional availability data.

These additional parameters require extra processing to retrieve the requested data, which will slow down the resource, sometimes substantially. They should therefore only be used where necessary.

Individual Seats

The Ingresso API can return a list of all available seats, allowing you to give your customers choice rather than forcing them to take the best available seats. If you have included add_seat_blocks in your request, the event is seated, and the supplier system supports seat selection, then we will return seat blocks containing seats. You can check for the presence of the seat blocks to determine whether you can offer seat selection to your customer.

Note: Ingresso offer an interactive seat map widget called Feather that can be embedded in your website, saving you development effort. This is an alternative to requesting individual seats via the API and displaying them to customers yourself.

Request

Example request

curl https://api.ticketswitch.com/f13/availability.v1 \
    -u "demo:demopass" \
    -d "perf_id=7AB-5" \
    -d "add_seat_blocks" \
    --compressed \
    -G
from pyticketswitch import Client

client = Client('demo', 'demopass')
ticket_types, meta = client.get_availability('7AB-5', seat_blocks=True)
Parameter Description
add_seat_blocks Include to retrieve individual seats (if, for example, you wish to offer seat selection to your customer). The inclusion of this parameter does not guarantee that individual seat data will be returned - this also depends on (a) whether the event is seated and (b) whether the supplier system supports seat selection.

Response

Example response

{
  "availability": {
    "ticket_type": [
      {
        "price_band": [
          {
            "absolute_saving": 0,
            "allows_leaving_single_seats": "always",
            "discount_code": "NORMAL",
            "discount_desc": "Regular Ticket",
            "free_seat_blocks": {
              "blocks_by_row": {
                "A": [
                  [
                    "A1",
                    "A2",
                    "A3",
                    "A4",
                    "A5",
                    "A6",
                    "A7",
                    "A8",
                    "A9",
                    "A10"
                  ]
                ],
                "B": [
                  [
                    "B2",
                    "B3",
                    "B4",
                    "B5",
                    "B6",
                    "B7",
                    "B8",
                    "B9"
                  ]
                ]
              },
              "restricted_view_seats": [
                "A1",
                "A2",
                "A10"
              ],
              "seats_by_text_message": {
                "Great seat": [
                  "A6"
                ]
              },
              "separators_by_row": {
                "A": "",
                "B": ""
              }
            },
            "is_offer": false,
            "non_offer_sale_seatprice": 50,
            "non_offer_sale_surcharge": 5,
            "number_available": 4,
            "percentage_saving": 0,
            "price_band_code": "A/pool",
            "sale_seatprice": 50,
            "sale_surcharge": 5
          },
          {
            "absolute_saving": 0,
            "allows_leaving_single_seats": "always",
            "discount_code": "NORMAL",
            "discount_desc": "Regular Ticket",
            "free_seat_blocks": {
              "blocks_by_row": {
                "C": [
                  [
                    "C3",
                    "C4",
                    "C5",
                    "C6"
                  ]
                ],
                "D": [
                  [
                    "D2",
                    "D3",
                    "D4",
                    "D5",
                    "D6",
                    "D7"
                  ]
                ]
              },
              "restricted_view_seats": [
                "C5",
                "C6"
              ],
              "seats_by_text_message": {
                "Haunted seat": [
                  "C6"
                ]
              },
              "separators_by_row": {
                "C": "",
                "D": ""
              }
            },
            "is_offer": false,
            "non_offer_sale_seatprice": 40,
            "non_offer_sale_surcharge": 5,
            "number_available": 4,
            "percentage_saving": 0,
            "price_band_code": "B/pool",
            "sale_seatprice": 40,
            "sale_surcharge": 5
          }
        ],
        "ticket_type_code": "STALLS",
        "ticket_type_desc": "Stalls"
      },
      {
        "price_band": [
          {
            "absolute_saving": 0,
            "allows_leaving_single_seats": "always",
            "discount_code": "NORMAL",
            "discount_desc": "Regular Ticket",
            "free_seat_blocks": {
              "blocks_by_row": {
                "E": [
                  [
                    "E4",
                    "E5"
                  ],
                  [
                    "E7",
                    "E8",
                    "E9"
                  ]
                ],
                "F": [
                  [
                    "F1",
                    "F2",
                    "F3"
                  ]
                ]
              },
              "restricted_view_seats": [],
              "seats_by_text_message": {},
              "separators_by_row": {
                "E": "",
                "F": ""
              }
            },
            "is_offer": false,
            "non_offer_sale_seatprice": 35,
            "non_offer_sale_surcharge": 5,
            "number_available": 4,
            "percentage_saving": 0,
            "price_band_code": "A/pool",
            "sale_seatprice": 35,
            "sale_surcharge": 5
          },
          {
            "absolute_saving": 0,
            "allows_leaving_single_seats": "always",
            "discount_code": "NORMAL",
            "discount_desc": "Regular Ticket",
            "free_seat_blocks": {
              "blocks_by_row": {
                "G": [
                  [
                    "G7",
                    "G8",
                    "G9",
                    "G10"
                  ]
                ],
                "H": [
                  [
                    "H1",
                    "H2",
                    "H3",
                    "H4"
                  ],
                  [
                    "H7",
                    "H8",
                    "H9",
                    "H10"
                  ]
                ]
              },
              "restricted_view_seats": [],
              "seats_by_text_message": {},
              "separators_by_row": {
                "G": "",
                "H": ""
              }
            },
            "is_offer": false,
            "non_offer_sale_seatprice": 30,
            "non_offer_sale_surcharge": 5,
            "number_available": 4,
            "percentage_saving": 0,
            "price_band_code": "B/pool",
            "sale_seatprice": 30,
            "sale_surcharge": 5
          }
        ],
        "ticket_type_code": "CIRCLE",
        "ticket_type_desc": "Dress Circle"
      }
    ]
  },
  "backend_is_broken": false,
  "backend_is_down": false,
  "backend_throttle_failed": false,
  "contiguous_seat_selection_only": false,
  "currency_code": "gbp",
  "currency_details": {
    "gbp": {
      "currency_code": "gbp",
      "currency_factor": 100,
      "currency_number": 826,
      "currency_places": 2,
      "currency_post_symbol": "",
      "currency_pre_symbol": "£"
    }
  },
  "valid_quantities": [
    1,
    2,
    3,
    4
  ]
}
from pyticketswitch.discount import Discount
from pyticketswitch.ticket_type import TicketType
from pyticketswitch.seat import Seat
from pyticketswitch.seat import SeatBlock
from pyticketswitch.price_band import PriceBand

[
    TicketType(
        code='STALLS',
        description='Stalls',
        price_bands=[
            PriceBand(
                code='A/pool',
                allows_leaving_single_seats='always',
                default_discount=Discount(
                    code='NORMAL',
                    description='Regular Ticket',
                    price_band_code='A/pool',
                    is_offer=False,
                    seatprice=50.0,
                    surcharge=5.0,
                    non_offer_seatprice=50.0,
                    non_offer_surcharge=5.0,
                    availability=4,
                    percentage_saving=0,
                    absolute_saving=0.0,
                ),
                example_seats_are_real=True,
                seat_blocks=[
                    SeatBlock(
                        length=10,
                        seats=[
                            Seat(
                                id='A1',
                                column='1',
                                row='A',
                                separator='',
                                is_restricted=True,
                                seat_text='',
                            ),
                            Seat(
                                id='A2',
                                column='2',
                                row='A',
                                separator='',
                                is_restricted=True,
                                seat_text='',
                            ),
                            Seat(
                                id='A3',
                                column='3',
                                row='A',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='A4',
                                column='4',
                                row='A',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='A5',
                                column='5',
                                row='A',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='A6',
                                column='6',
                                row='A',
                                separator='',
                                is_restricted=False,
                                seat_text='Great seat',
                            ),
                            Seat(
                                id='A7',
                                column='7',
                                row='A',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='A8',
                                column='8',
                                row='A',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='A9',
                                column='9',
                                row='A',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='A10',
                                column='10',
                                row='A',
                                separator='',
                                is_restricted=True,
                                seat_text='',
                            )
                        ],
                    ),
                    SeatBlock(
                        length=8,
                        seats=[
                            Seat(
                                id='B2',
                                column='2',
                                row='B',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='B3',
                                column='3',
                                row='B',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='B4',
                                column='4',
                                row='B',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='B5',
                                column='5',
                                row='B',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='B6',
                                column='6',
                                row='B',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='B7',
                                column='7',
                                row='B',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='B8',
                                column='8',
                                row='B',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='B9',
                                column='9',
                                row='B',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            )
                        ],
                    )
                ],
            ),
            PriceBand(
                code='B/pool',
                allows_leaving_single_seats='always',
                default_discount=Discount(
                    code='NORMAL',
                    description='Regular Ticket',
                    price_band_code='B/pool',
                    is_offer=False,
                    seatprice=40.0,
                    surcharge=5.0,
                    non_offer_seatprice=40.0,
                    non_offer_surcharge=5.0,
                    availability=4,
                    percentage_saving=0,
                    absolute_saving=0.0,
                ),
                example_seats_are_real=True,
                seat_blocks=[
                    SeatBlock(
                        length=4,
                        seats=[
                            Seat(
                                id='C3',
                                column='3',
                                row='C',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='C4',
                                column='4',
                                row='C',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='C5',
                                column='5',
                                row='C',
                                separator='',
                                is_restricted=True,
                                seat_text='',
                            ),
                            Seat(
                                id='C6',
                                column='6',
                                row='C',
                                separator='',
                                is_restricted=True,
                                seat_text='Haunted seat',
                            )
                        ],
                    ),
                    SeatBlock(
                        length=6,
                        seats=[
                            Seat(
                                id='D2',
                                column='2',
                                row='D',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='D3',
                                column='3',
                                row='D',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='D4',
                                column='4',
                                row='D',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='D5',
                                column='5',
                                row='D',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='D6',
                                column='6',
                                row='D',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='D7',
                                column='7',
                                row='D',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            )
                        ],
                    )
                ],
            )
        ],
    ),
    TicketType(
        code='CIRCLE',
        description='Dress Circle',
        price_bands=[
            PriceBand(
                code='A/pool',
                allows_leaving_single_seats='always',
                default_discount=Discount(
                    code='NORMAL',
                    description='Regular Ticket',
                    price_band_code='A/pool',
                    is_offer=False,
                    seatprice=35.0,
                    surcharge=5.0,
                    non_offer_seatprice=35.0,
                    non_offer_surcharge=5.0,
                    availability=4,
                    percentage_saving=0,
                    absolute_saving=0.0,
                ),
                example_seats_are_real=True,
                seat_blocks=[
                    SeatBlock(
                        length=2,
                        seats=[
                            Seat(
                                id='E4',
                                column='4',
                                row='E',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='E5',
                                column='5',
                                row='E',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            )
                        ],
                    ),
                    SeatBlock(
                        length=3,
                        seats=[
                            Seat(
                                id='E7',
                                column='7',
                                row='E',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='E8',
                                column='8',
                                row='E',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='E9',
                                column='9',
                                row='E',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            )
                        ],
                    ),
                    SeatBlock(
                        length=3,
                        seats=[
                            Seat(
                                id='F1',
                                column='1',
                                row='F',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='F2',
                                column='2',
                                row='F',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='F3',
                                column='3',
                                row='F',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            )
                        ],
                    )
                ],
            ),
            PriceBand(
                code='B/pool',
                allows_leaving_single_seats='always',
                default_discount=Discount(
                    code='NORMAL',
                    description='Regular Ticket',
                    price_band_code='B/pool',
                    is_offer=False,
                    seatprice=30.0,
                    surcharge=5.0,
                    non_offer_seatprice=30.0,
                    non_offer_surcharge=5.0,
                    availability=4,
                    percentage_saving=0,
                    absolute_saving=0.0,
                ),
                example_seats_are_real=True,
                seat_blocks=[
                    SeatBlock(
                        length=4,
                        seats=[
                            Seat(
                                id='G7',
                                column='7',
                                row='G',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='G8',
                                column='8',
                                row='G',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='G9',
                                column='9',
                                row='G',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='G10',
                                column='10',
                                row='G',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            )
                        ],
                    ),
                    SeatBlock(
                        length=4,
                        seats=[
                            Seat(
                                id='H1',
                                column='1',
                                row='H',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='H2',
                                column='2',
                                row='H',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='H3',
                                column='3',
                                row='H',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='H4',
                                column='4',
                                row='H',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            )
                        ],
                    ),
                    SeatBlock(
                        length=4,
                        seats=[
                            Seat(
                                id='H7',
                                column='7',
                                row='H',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='H8',
                                column='8',
                                row='H',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='H9',
                                column='9',
                                row='H',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            ),
                            Seat(
                                id='H10',
                                column='10',
                                row='H',
                                separator='',
                                is_restricted=False,
                                seat_text='',
                            )
                        ],
                    )
                ],
            )
        ],
    )
]

The response includes the following attributes in the free_seat_blocks:

Attribute Description
blocks_by_row A list of the rows that contain seats. The row identifier is the key and the value is an array of contiguous seat blocks within that row. Within each contiguous seat block there is an array of seat IDs. These seat IDs all begin with the row identifier, and include the column identifier. The IDs should be displayed to the customer. Note that when contiguous_seat_selection_only = true then you can only reserve seats within a single seat block, and only in a consecutive order in the array. In most cases contiguous_seat_selection_only = false and you can select any seats from free_seat_blocks.
restricted_view_seats A list of seat IDs that are classified as having a restricted view. You must indicate this to your customer before they purchase tickets. Note that it is possible for seats to be included in this array but to not have a seat message. Your application should still display a message to the customer in this case.
seats_by_text_message A list of seat messages. The key is the seat message, and the value is an array of seat IDs that the message applies to. When you see a seat message you must display this to your customer.
separators_by_row The row identifier is the key, the value is a separator. Separators are between the row ID and the column ID, for example seat ID A.10 has a separator of ., a row ID of A and a column ID of 10. In most cases there is no separator, which is represented by an empty string.

Example Seats

Example seats can be requested and displayed alongside the list of available ticket types and price bands. This is a simpler option to show seats to your customer alongside the list of price bands without needing to request individual seats and do the work to display them on a seating plan or similar. If you plan to display individual seats then there is no need to also request example seats.

Request

Example request

curl https://api.ticketswitch.com/f13/availability.v1 \
    -u "demo:demopass" \
    -d "perf_id=7AB-5" \
    -d "no_of_seats=3" \
    -d "add_example_seats" \
    --compressed \
    -G
from pyticketswitch import Client

client = Client('demo', 'demopass')
ticket_types, meta = client.get_availability('7AB-5', example_seats=True)
Parameter Description
add_example_seats Include to retrieve example seats. These can be displayed alongside the ticket options when presenting availability to customers. The inclusion of this parameter does not guarantee that example seats data will be returned - this also depends on (a) whether the event is seated and (b) whether the supplier system returns seats at availability time.

Response

Example response

{
  "availability": {
    "ticket_type": [
      {
        "price_band": [
          {
            "absolute_saving": 0,
            "allows_leaving_single_seats": "always",
            "discount_code": "NORMAL",
            "discount_desc": "Regular Ticket",
            "is_offer": false,
            "non_offer_sale_seatprice": 50,
            "non_offer_sale_surcharge": 5,
            "number_available": 4,
            "percentage_saving": 0,
            "price_band_code": "A/pool",
            "sale_seatprice": 50,
            "sale_surcharge": 5
          },
          {
            "absolute_saving": 0,
            "allows_leaving_single_seats": "always",
            "discount_code": "NORMAL",
            "discount_desc": "Regular Ticket",
            "is_offer": false,
            "non_offer_sale_seatprice": 40,
            "non_offer_sale_surcharge": 5,
            "number_available": 4,
            "percentage_saving": 0,
            "price_band_code": "B/pool",
            "sale_seatprice": 40,
            "sale_surcharge": 5
          }
        ],
        "ticket_type_code": "STALLS",
        "ticket_type_desc": "Stalls"
      },
      {
        "price_band": [
          {
            "absolute_saving": 0,
            "allows_leaving_single_seats": "always",
            "discount_code": "NORMAL",
            "discount_desc": "Regular Ticket",
            "example_seats": [
              {
                "col_id": "1",
                "full_id": "F1",
                "is_restricted_view": false,
                "row_id": "F"
              },
              {
                "col_id": "2",
                "full_id": "F2",
                "is_restricted_view": false,
                "row_id": "F"
              }
            ],
            "example_seats_are_real": false,
            "is_offer": false,
            "non_offer_sale_seatprice": 35,
            "non_offer_sale_surcharge": 5,
            "number_available": 4,
            "percentage_saving": 0,
            "price_band_code": "A/pool",
            "sale_seatprice": 35,
            "sale_surcharge": 5
          },
          {
            "absolute_saving": 0,
            "allows_leaving_single_seats": "always",
            "discount_code": "NORMAL",
            "discount_desc": "Regular Ticket",
            "is_offer": false,
            "non_offer_sale_seatprice": 30,
            "non_offer_sale_surcharge": 5,
            "number_available": 4,
            "percentage_saving": 0,
            "price_band_code": "B/pool",
            "sale_seatprice": 30,
            "sale_surcharge": 5
          }
        ],
        "ticket_type_code": "CIRCLE",
        "ticket_type_desc": "Dress Circle"
      }
    ]
  },
  "backend_is_broken": false,
  "backend_is_down": false,
  "backend_throttle_failed": false,
  "contiguous_seat_selection_only": false,
  "currency_code": "gbp",
  "currency_details": {
    "gbp": {
      "currency_code": "gbp",
      "currency_factor": 100,
      "currency_number": 826,
      "currency_places": 2,
      "currency_post_symbol": "",
      "currency_pre_symbol": "£"
    }
  },
  "valid_quantities": [
    1,
    2,
    3,
    4
  ]
}
from pyticketswitch.price_band import PriceBand
from pyticketswitch.discount import Discount
from pyticketswitch.ticket_type import TicketType
from pyticketswitch.seat import Seat

[
    TicketType(
        code='STALLS',
        description='Stalls',
        price_bands=[
            PriceBand(
                code='A/pool',
                allows_leaving_single_seats='always',
                default_discount=Discount(
                    code='NORMAL',
                    description='Regular Ticket',
                    price_band_code='A/pool',
                    is_offer=False,
                    seatprice=50.0,
                    surcharge=5.0,
                    non_offer_seatprice=50.0,
                    non_offer_surcharge=5.0,
                    availability=4,
                    percentage_saving=0,
                    absolute_saving=0.0,
                ),
                example_seats=[
                    Seat(
                        id='B2',
                        column='2',
                        row='B',
                        separator='',
                        is_restricted=False,
                    ),
                    Seat(
                        id='B3',
                        column='3',
                        row='B',
                        separator='',
                        is_restricted=False,
                    )
                ],
                example_seats_are_real=False,
            ),
            PriceBand(
                code='B/pool',
                allows_leaving_single_seats='always',
                default_discount=Discount(
                    code='NORMAL',
                    description='Regular Ticket',
                    price_band_code='B/pool',
                    is_offer=False,
                    seatprice=40.0,
                    surcharge=5.0,
                    non_offer_seatprice=40.0,
                    non_offer_surcharge=5.0,
                    availability=4,
                    percentage_saving=0,
                    absolute_saving=0.0,
                ),
                example_seats_are_real=True,
            )
        ],
    ),
    TicketType(
        code='CIRCLE',
        description='Dress Circle',
        price_bands=[
            PriceBand(
                code='A/pool',
                allows_leaving_single_seats='always',
                default_discount=Discount(
                    code='NORMAL',
                    description='Regular Ticket',
                    price_band_code='A/pool',
                    is_offer=False,
                    seatprice=35.0,
                    surcharge=5.0,
                    non_offer_seatprice=35.0,
                    non_offer_surcharge=5.0,
                    availability=4,
                    percentage_saving=0,
                    absolute_saving=0.0,
                ),
                example_seats_are_real=True,
            ),
            PriceBand(
                code='B/pool',
                allows_leaving_single_seats='always',
                default_discount=Discount(
                    code='NORMAL',
                    description='Regular Ticket',
                    price_band_code='B/pool',
                    is_offer=False,
                    seatprice=30.0,
                    surcharge=5.0,
                    non_offer_seatprice=30.0,
                    non_offer_surcharge=5.0,
                    availability=4,
                    percentage_saving=0,
                    absolute_saving=0.0,
                ),
                example_seats_are_real=True,
            )
        ],
    )
]

If the event supports example seats the response includes several attributes in example_seats.

Attribute Description
example_seats_are_real If true the example seats are taken from a list of available seats, and they are the seats the customer is likely to receive when they reserve tickets. This is the most common scenario. If false the example seats are taken from previous reservations and are therefore less reliable.
id_details The description of an individual seat.
id_details.col_id The column identifier, normally a number.
id_details.full_id The unique identifier for the seat.
id_details.is_restricted_view true if the seat is marked as having a restricted view.
id_details.row_id The row identifier, normally a letter.
id_details.seat_subdata Ignore - this will be removed soon.
id_details.seat_text (Optional) A description of the seat that should be displayed to the customer. If the seat has a restricted view this text will normally be present to describe the restriction in more detail, but it should be displayed in all cases.
id_details.seat_text_code Ignore - this will be removed soon.
id_details.separator Sometimes a seat ID can include a separator character such as ., e.g. A.23.

Commission

Some partners wish to view the predicted commission they will earn on each ticket up front, before the sale is made. This could be to support agents that want to know what they will earn, or to support custom repricing.

Availability will return the predicted per ticket commission you will earn. If you subtract commission from the total ticket price (sale_seatprice + sale_surcharge) you have the net price of the ticket.

There are important caveats to note:

  1. The price and commission is not guaranteed until tickets are reserved. Ingresso do not store the commission values returned in this availability request so we cannot refer to it later. Some suppliers have rules where the price will change after tickets are reserved (for example lowering the price to a family rate when 2 adults and 2 children are selected) - that would likely also affect commission. Similarly, the number of tickets can impact the commission but the number of tickets is normally unknown when requesting availability. It is also possible but unlikely for Ingresso’s commission configuration to change between you requesting availability and reserving. For these reasons commission values are marked as “predicted”.

  2. It is possible for the commission currency to be different to the selling currency, since the commission currency usually relates to the supplier while the selling currency is targeted at the end customer. When the currencies are different you can’t simply subtract commission from total ticket price.

Request

Example request

curl https://api.ticketswitch.com/f13/availability.v1 \
    -u "demo:demopass" \
    -d "perf_id=6IF-B5P" \
    -d "req_predicted_commission" \
    --compressed \
    -G
from pyticketswitch import Client

client = Client('demo', 'demopass')
ticket_types, meta = client.get_availability('6IF-B5P', user_commission=True)
Parameter Description
req_predicted_commission Include to retrieve commission data. For most partners this will include predicted_user_commission only (the predicted amount you earn per ticket). Some partners will also see predicted_gross_commission, which is the total commission available to be shared between Ingresso and our partner. By default you will see predicted_user_commission only - if you think you need to see predicted_gross_commission as well then please get in touch.

Response

Example response

{
  "availability": {
    "ticket_type": [
      {
        "price_band": [
          {
            "absolute_saving": 0,
            "allows_leaving_single_seats": "always",
            "discount_code": "",
            "discount_desc": "",
            "predicted_gross_commission": {
              "amount_excluding_vat": 4.88,
              "amount_including_vat": 5.85,
              "commission_currency_code": "gbp"
            },
            "is_offer": false,
            "non_offer_sale_seatprice": 35,
            "non_offer_sale_surcharge": 4,
            "number_available": 6,
            "percentage_saving": 0,
            "price_band_code": "A/pool",
            "sale_seatprice": 35,
            "sale_surcharge": 4,
            "predicted_user_commission": {
              "amount_excluding_vat": 2.19,
              "amount_including_vat": 2.63,
              "commission_currency_code": "gbp"
            }
          },
          {
            "absolute_saving": 0,
            "allows_leaving_single_seats": "always",
            "discount_code": "",
            "discount_desc": "",
            "predicted_gross_commission": {
              "amount_excluding_vat": 4.25,
              "amount_including_vat": 5.1,
              "commission_currency_code": "gbp"
            },
            "is_offer": false,
            "non_offer_sale_seatprice": 30,
            "non_offer_sale_surcharge": 4,
            "number_available": 6,
            "percentage_saving": 0,
            "price_band_code": "B/pool",
            "sale_seatprice": 30,
            "sale_surcharge": 4,
            "predicted_user_commission": {
              "amount_excluding_vat": 1.91,
              "amount_including_vat": 2.3,
              "commission_currency_code": "gbp"
            }
          },
          {
            "absolute_saving": 0,
            "allows_leaving_single_seats": "always",
            "discount_code": "",
            "discount_desc": "",
            "predicted_gross_commission": {
              "amount_excluding_vat": 3.63,
              "amount_including_vat": 4.35,
              "commission_currency_code": "gbp"
            },
            "is_offer": false,
            "non_offer_sale_seatprice": 25,
            "non_offer_sale_surcharge": 4,
            "number_available": 6,
            "percentage_saving": 0,
            "price_band_code": "C/pool",
            "sale_seatprice": 25,
            "sale_surcharge": 4,
            "predicted_user_commission": {
              "amount_excluding_vat": 1.63,
              "amount_including_vat": 1.96,
              "commission_currency_code": "gbp"
            }
          }
        ],
        "ticket_type_code": "CIRCLE",
        "ticket_type_desc": "Upper circle"
      },
      {
        "price_band": [
          {
            "absolute_saving": 0,
            "allows_leaving_single_seats": "always",
            "discount_code": "",
            "discount_desc": "",
            "predicted_gross_commission": {
              "amount_excluding_vat": 3,
              "amount_including_vat": 3.6,
              "commission_currency_code": "gbp"
            },
            "is_offer": false,
            "non_offer_sale_seatprice": 21,
            "non_offer_sale_surcharge": 3,
            "number_available": 6,
            "percentage_saving": 0,
            "price_band_code": "A/pool",
            "sale_seatprice": 21,
            "sale_surcharge": 3,
            "predicted_user_commission": {
              "amount_excluding_vat": 1.35,
              "amount_including_vat": 1.62,
              "commission_currency_code": "gbp"
            }
          },
          {
            "absolute_saving": 0,
            "allows_leaving_single_seats": "always",
            "discount_code": "",
            "discount_desc": "",
            "predicted_gross_commission": {
              "amount_excluding_vat": 2.63,
              "amount_including_vat": 3.15,
              "commission_currency_code": "gbp"
            },
            "is_offer": false,
            "non_offer_sale_seatprice": 18,
            "non_offer_sale_surcharge": 3,
            "number_available": 3,
            "percentage_saving": 0,
            "price_band_code": "B/pool",
            "sale_seatprice": 18,
            "sale_surcharge": 3,
            "predicted_user_commission": {
              "amount_excluding_vat": 1.18,
              "amount_including_vat": 1.42,
              "commission_currency_code": "gbp"
            }
          }
        ],
        "ticket_type_code": "STALLS",
        "ticket_type_desc": "Stalls"
      },
      {
        "price_band": [
          {
            "absolute_saving": 0,
            "allows_leaving_single_seats": "always",
            "discount_code": "",
            "discount_desc": "",
            "predicted_gross_commission": {
              "amount_excluding_vat": 6.5,
              "amount_including_vat": 7.8,
              "commission_currency_code": "gbp"
            },
            "is_offer": false,
            "non_offer_sale_seatprice": 47,
            "non_offer_sale_surcharge": 5,
            "number_available": 6,
            "percentage_saving": 0,
            "price_band_code": "A/pool",
            "sale_seatprice": 47,
            "sale_surcharge": 5,
            "predicted_user_commission": {
              "amount_excluding_vat": 2.93,
              "amount_including_vat": 3.51,
              "commission_currency_code": "gbp"
            }
          }
        ],
        "ticket_type_code": "BALCONY",
        "ticket_type_desc": "Balcony"
      }
    ]
  },
  "backend_is_broken": false,
  "backend_is_down": false,
  "backend_throttle_failed": false,
  "contiguous_seat_selection_only": true,
  "currency_code": "gbp",
  "currency_details": {
    "gbp": {
      "currency_code": "gbp",
      "currency_factor": 100,
      "currency_number": 826,
      "currency_places": 2,
      "currency_post_symbol": "",
      "currency_pre_symbol": "£"
    }
  },
  "valid_quantities": [
    1,
    2,
    3,
    4,
    5,
    6
  ]
}
from pyticketswitch.commission import Commission
from pyticketswitch.ticket_type import TicketType
from pyticketswitch.discount import Discount
from pyticketswitch.price_band import PriceBand

[
    TicketType(
        code='CIRCLE',
        description='Upper circle',
        price_bands=[
            PriceBand(
                code='A/pool',
                allows_leaving_single_seats='always',
                default_discount=Discount(
                    code='',
                    description='',
                    price_band_code='A/pool',
                    is_offer=False,
                    seatprice=35.0,
                    surcharge=4.0,
                    non_offer_seatprice=35.0,
                    non_offer_surcharge=4.0,
                    availability=6,
                    percentage_saving=0,
                    absolute_saving=0.0,
                ),
                example_seats_are_real=True,
                user_commission=Commission(
                    including_vat=2.63,
                    excluding_vat=2.19,
                    currency_code='gbp',
                ),
            ),
            PriceBand(
                code='B/pool',
                allows_leaving_single_seats='always',
                default_discount=Discount(
                    code='',
                    description='',
                    price_band_code='B/pool',
                    is_offer=False,
                    seatprice=30.0,
                    surcharge=4.0,
                    non_offer_seatprice=30.0,
                    non_offer_surcharge=4.0,
                    availability=6,
                    percentage_saving=0,
                    absolute_saving=0.0,
                ),
                example_seats_are_real=True,
                user_commission=Commission(
                    including_vat=2.3,
                    excluding_vat=1.91,
                    currency_code='gbp',
                ),
            ),
            PriceBand(
                code='C/pool',
                allows_leaving_single_seats='always',
                default_discount=Discount(
                    code='',
                    description='',
                    price_band_code='C/pool',
                    is_offer=False,
                    seatprice=25.0,
                    surcharge=4.0,
                    non_offer_seatprice=25.0,
                    non_offer_surcharge=4.0,
                    availability=6,
                    percentage_saving=0,
                    absolute_saving=0.0,
                ),
                example_seats_are_real=True,
                user_commission=Commission(
                    including_vat=1.96,
                    excluding_vat=1.63,
                    currency_code='gbp',
                ),
            )
        ],
    ),
    TicketType(
        code='STALLS',
        description='Stalls',
        price_bands=[
            PriceBand(
                code='A/pool',
                allows_leaving_single_seats='always',
                default_discount=Discount(
                    code='',
                    description='',
                    price_band_code='A/pool',
                    is_offer=False,
                    seatprice=21.0,
                    surcharge=3.0,
                    non_offer_seatprice=21.0,
                    non_offer_surcharge=3.0,
                    availability=6,
                    percentage_saving=0,
                    absolute_saving=0.0,
                ),
                example_seats_are_real=True,
                user_commission=Commission(
                    including_vat=1.62,
                    excluding_vat=1.35,
                    currency_code='gbp',
                ),
            ),
            PriceBand(
                code='B/pool',
                allows_leaving_single_seats='always',
                default_discount=Discount(
                    code='',
                    description='',
                    price_band_code='B/pool',
                    is_offer=False,
                    seatprice=18.0,
                    surcharge=3.0,
                    non_offer_seatprice=18.0,
                    non_offer_surcharge=3.0,
                    availability=3,
                    percentage_saving=0,
                    absolute_saving=0.0,
                ),
                example_seats_are_real=True,
                user_commission=Commission(
                    including_vat=1.42,
                    excluding_vat=1.18,
                    currency_code='gbp',
                ),
            )
        ],
    ),
    TicketType(
        code='BALCONY',
        description='Balcony',
        price_bands=[
            PriceBand(
                code='A/pool',
                allows_leaving_single_seats='always',
                default_discount=Discount(
                    code='',
                    description='',
                    price_band_code='A/pool',
                    is_offer=False,
                    seatprice=47.0,
                    surcharge=5.0,
                    non_offer_seatprice=47.0,
                    non_offer_surcharge=5.0,
                    availability=6,
                    percentage_saving=0,
                    absolute_saving=0.0,
                ),
                example_seats_are_real=True,
                user_commission=Commission(
                    including_vat=3.51,
                    excluding_vat=2.93,
                    currency_code='gbp',
                ),
            )
        ],
    )
]

The response includes several attributes within the predicted_user_commission dictionary. Some partners will also see predicted_gross_commission which includes the same attributes.

Attribute Description
amount_excluding_vat The predicted commission you will earn per ticket, excluding sales tax.
amount_including_vat The predicted commission you will earn per ticket, including sales tax.
commission_currency_code The commission currency (note that this can be different to the currency of the price paid by the customer).

Add Discounts

A discount represents a price type or concession that is available for a set of available tickets.

Request

Example request

curl https://api.ticketswitch.com/f13/availability.v1 \
    -u "demo:demopass" \
    -d "perf_id=6IF-B5P" \
    -d "add_discounts" \
    --compressed \
    -G
from pyticketswitch import Client

client = Client('demo', 'demopass')
ticket_types, meta = client.get_availability('6IF-B5P', discounts=True)
Parameter Description
add_discounts

Response

Example response - including seat listing

{
  "availability": {
    "ticket_type": [
      {
        "price_band": [
          {
            "absolute_saving": 0,
            "allows_leaving_single_seats": "always",
            "discount_code": "",
            "discount_desc": "",
            "is_offer": false,
            "non_offer_sale_seatprice": 35,
            "non_offer_sale_surcharge": 0,
            "number_available": 6,
            "percentage_saving": 0,
            "possible_discounts": {
              "discount": [
                {
                  "absolute_saving": 0,
                  "discount_code": "ADULT",
                  "discount_desc": "Adult standard",
                  "is_offer": false,
                  "non_offer_sale_seatprice": 35,
                  "non_offer_sale_surcharge": 0,
                  "number_available": 6,
                  "percentage_saving": 0,
                  "price_band_code": "A/pool",
                  "sale_seatprice": 35,
                  "sale_surcharge": 0
                },
                {
                  "absolute_saving": 0,
                  "discount_code": "CHILD",
                  "discount_desc": "Child rate",
                  "is_offer": false,
                  "non_offer_sale_seatprice": 18,
                  "non_offer_sale_surcharge": 0,
                  "number_available": 6,
                  "percentage_saving": 0,
                  "price_band_code": "A/pool",
                  "sale_seatprice": 18,
                  "sale_surcharge": 0
                },
                {
                  "absolute_saving": 0,
                  "discount_code": "STUDENT",
                  "discount_desc": "Student rate",
                  "is_offer": false,
                  "non_offer_sale_seatprice": 26,
                  "non_offer_sale_surcharge": 0,
                  "number_available": 6,
                  "percentage_saving": 0,
                  "price_band_code": "A/pool",
                  "sale_seatprice": 26,
                  "sale_surcharge": 0
                },
                {
                  "absolute_saving": 0,
                  "discount_code": "OAP",
                  "discount_desc": "Senior citizen rate",
                  "is_offer": false,
                  "non_offer_sale_seatprice": 28,
                  "non_offer_sale_surcharge": 0,
                  "number_available": 6,
                  "percentage_saving": 0,
                  "price_band_code": "A/pool",
                  "sale_seatprice": 28,
                  "sale_surcharge": 0
                }
              ]
            },
            "price_band_code": "A/pool",
            "sale_seatprice": 35,
            "sale_surcharge": 0
          },
          {
            "absolute_saving": 0,
            "allows_leaving_single_seats": "always",
            "discount_code": "",
            "discount_desc": "",
            "is_offer": false,
            "non_offer_sale_seatprice": 30,
            "non_offer_sale_surcharge": 0,
            "number_available": 6,
            "percentage_saving": 0,
            "possible_discounts": {
              "discount": [
                {
                  "absolute_saving": 0,
                  "discount_code": "ADULT",
                  "discount_desc": "Adult standard",
                  "is_offer": false,
                  "non_offer_sale_seatprice": 30,
                  "non_offer_sale_surcharge": 0,
                  "number_available": 6,
                  "percentage_saving": 0,
                  "price_band_code": "B/pool",
                  "sale_seatprice": 30,
                  "sale_surcharge": 0
                },
                {
                  "absolute_saving": 0,
                  "discount_code": "CHILD",
                  "discount_desc": "Child rate",
                  "is_offer": false,
                  "non_offer_sale_seatprice": 15,
                  "non_offer_sale_surcharge": 0,
                  "number_available": 6,
                  "percentage_saving": 0,
                  "price_band_code": "B/pool",
                  "sale_seatprice": 15,
                  "sale_surcharge": 0
                }
              ]
            },
            "price_band_code": "B/pool",
            "sale_seatprice": 30,
            "sale_surcharge": 0
          },
          {
            "absolute_saving": 0,
            "allows_leaving_single_seats": "always",
            "discount_code": "",
            "discount_desc": "",
            "is_offer": false,
            "non_offer_sale_seatprice": 25,
            "non_offer_sale_surcharge": 0,
            "number_available": 6,
            "percentage_saving": 0,
            "possible_discounts": {
              "discount": [
                {
                  "absolute_saving": 0,
                  "discount_code": "ADULT",
                  "discount_desc": "Adult standard",
                  "is_offer": false,
                  "non_offer_sale_seatprice": 25,
                  "non_offer_sale_surcharge": 0,
                  "number_available": 6,
                  "percentage_saving": 0,
                  "price_band_code": "C/pool",
                  "sale_seatprice": 25,
                  "sale_surcharge": 0
                },
                {
                  "absolute_saving": 0,
                  "discount_code": "CHILD",
                  "discount_desc": "Child rate",
                  "is_offer": false,
                  "non_offer_sale_seatprice": 13,
                  "non_offer_sale_surcharge": 0,
                  "number_available": 6,
                  "percentage_saving": 0,
                  "price_band_code": "C/pool",
                  "sale_seatprice": 13,
                  "sale_surcharge": 0
                },
                {
                  "absolute_saving": 0,
                  "discount_code": "STUDENT",
                  "discount_desc": "Student rate",
                  "is_offer": false,
                  "non_offer_sale_seatprice": 19,
                  "non_offer_sale_surcharge": 0,
                  "number_available": 6,
                  "percentage_saving": 0,
                  "price_band_code": "C/pool",
                  "sale_seatprice": 19,
                  "sale_surcharge": 0
                },
                {
                  "absolute_saving": 0,
                  "discount_code": "OAP",
                  "discount_desc": "Senior citizen rate",
                  "is_offer": false,
                  "non_offer_sale_seatprice": 20,
                  "non_offer_sale_surcharge": 0,
                  "number_available": 6,
                  "percentage_saving": 0,
                  "price_band_code": "C/pool",
                  "sale_seatprice": 20,
                  "sale_surcharge": 0
                }
              ]
            },
            "price_band_code": "C/pool",
            "sale_seatprice": 25,
            "sale_surcharge": 0
          }
        ],
        "ticket_type_code": "CIRCLE",
        "ticket_type_desc": "Upper circle"
      },
      {
        "price_band": [
          {
            "absolute_saving": 0,
            "allows_leaving_single_seats": "always",
            "discount_code": "",
            "discount_desc": "",
            "is_offer": false,
            "non_offer_sale_seatprice": 21,
            "non_offer_sale_surcharge": 0,
            "number_available": 6,
            "percentage_saving": 0,
            "possible_discounts": {
              "discount": [
                {
                  "absolute_saving": 0,
                  "discount_code": "ADULT",
                  "discount_desc": "Adult standard",
                  "is_offer": false,
                  "non_offer_sale_seatprice": 21,
                  "non_offer_sale_surcharge": 0,
                  "number_available": 6,
                  "percentage_saving": 0,
                  "price_band_code": "A/pool",
                  "sale_seatprice": 21,
                  "sale_surcharge": 0
                },
                {
                  "absolute_saving": 0,
                  "discount_code": "CHILD",
                  "discount_desc": "Child rate",
                  "is_offer": false,
                  "non_offer_sale_seatprice": 11,
                  "non_offer_sale_surcharge": 0,
                  "number_available": 6,
                  "percentage_saving": 0,
                  "price_band_code": "A/pool",
                  "sale_seatprice": 11,
                  "sale_surcharge": 0
                },
                {
                  "absolute_saving": 0,
                  "discount_code": "STUDENT",
                  "discount_desc": "Student rate",
                  "is_offer": false,
                  "non_offer_sale_seatprice": 16,
                  "non_offer_sale_surcharge": 0,
                  "number_available": 6,
                  "percentage_saving": 0,
                  "price_band_code": "A/pool",
                  "sale_seatprice": 16,
                  "sale_surcharge": 0
                },
                {
                  "absolute_saving": 0,
                  "discount_code": "OAP",
                  "discount_desc": "Senior citizen rate",
                  "is_offer": false,
                  "non_offer_sale_seatprice": 17,
                  "non_offer_sale_surcharge": 0,
                  "number_available": 6,
                  "percentage_saving": 0,
                  "price_band_code": "A/pool",
                  "sale_seatprice": 17,
                  "sale_surcharge": 0
                }
              ]
            },
            "price_band_code": "A/pool",
            "sale_seatprice": 21,
            "sale_surcharge": 0
          },
          {
            "absolute_saving": 0,
            "allows_leaving_single_seats": "always",
            "discount_code": "",
            "discount_desc": "",
            "is_offer": false,
            "non_offer_sale_seatprice": 18,
            "non_offer_sale_surcharge": 0,
            "number_available": 3,
            "percentage_saving": 0,
            "possible_discounts": {
              "discount": [
                {
                  "absolute_saving": 0,
                  "discount_code": "ADULT",
                  "discount_desc": "Adult standard",
                  "is_offer": false,
                  "non_offer_sale_seatprice": 18,
                  "non_offer_sale_surcharge": 0,
                  "number_available": 3,
                  "percentage_saving": 0,
                  "price_band_code": "B/pool",
                  "sale_seatprice": 18,
                  "sale_surcharge": 0
                },
                {
                  "absolute_saving": 0,
                  "discount_code": "CHILD",
                  "discount_desc": "Child rate",
                  "is_offer": false,
                  "non_offer_sale_seatprice": 9,
                  "non_offer_sale_surcharge": 0,
                  "number_available": 3,
                  "percentage_saving": 0,
                  "price_band_code": "B/pool",
                  "sale_seatprice": 9,
                  "sale_surcharge": 0
                }
              ]
            },
            "price_band_code": "B/pool",
            "sale_seatprice": 18,
            "sale_surcharge": 0
          }
        ],
        "ticket_type_code": "STALLS",
        "ticket_type_desc": "Stalls"
      },
      {
        "price_band": [
          {
            "absolute_saving": 0,
            "allows_leaving_single_seats": "always",
            "discount_code": "",
            "discount_desc": "",
            "is_offer": false,
            "non_offer_sale_seatprice": 47,
            "non_offer_sale_surcharge": 0,
            "number_available": 6,
            "percentage_saving": 0,
            "possible_discounts": {
              "discount": [
                {
                  "absolute_saving": 0,
                  "discount_code": "ADULT",
                  "discount_desc": "Adult standard",
                  "is_offer": false,
                  "non_offer_sale_seatprice": 47,
                  "non_offer_sale_surcharge": 0,
                  "number_available": 6,
                  "percentage_saving": 0,
                  "price_band_code": "A/pool",
                  "sale_seatprice": 47,
                  "sale_surcharge": 0
                },
                {
                  "absolute_saving": 0,
                  "discount_code": "CHILD",
                  "discount_desc": "Child rate",
                  "is_offer": false,
                  "non_offer_sale_seatprice": 24,
                  "non_offer_sale_surcharge": 0,
                  "number_available": 6,
                  "percentage_saving": 0,
                  "price_band_code": "A/pool",
                  "sale_seatprice": 24,
                  "sale_surcharge": 0
                },
                {
                  "absolute_saving": 0,
                  "discount_code": "STUDENT",
                  "discount_desc": "Student rate",
                  "is_offer": false,
                  "non_offer_sale_seatprice": 35,
                  "non_offer_sale_surcharge": 0,
                  "number_available": 6,
                  "percentage_saving": 0,
                  "price_band_code": "A/pool",
                  "sale_seatprice": 35,
                  "sale_surcharge": 0
                },
                {
                  "absolute_saving": 0,
                  "discount_code": "OAP",
                  "discount_desc": "Senior citizen rate",
                  "is_offer": false,
                  "non_offer_sale_seatprice": 38,
                  "non_offer_sale_surcharge": 0,
                  "number_available": 6,
                  "percentage_saving": 0,
                  "price_band_code": "A/pool",
                  "sale_seatprice": 38,
                  "sale_surcharge": 0
                }
              ]
            },
            "price_band_code": "A/pool",
            "sale_seatprice": 47,
            "sale_surcharge": 0
          }
        ],
        "ticket_type_code": "BALCONY",
        "ticket_type_desc": "Balcony"
      }
    ]
  },
  "backend_is_broken": false,
  "backend_is_down": false,
  "backend_throttle_failed": false,
  "contiguous_seat_selection_only": true,
  "currency": {
    "currency_code": "gbp"
  },
  "valid_quantities": [
    1,
    2,
    3,
    4,
    5,
    6
  ]
}
from pyticketswitch.price_band import PriceBand
from pyticketswitch.ticket_type import TicketType
from pyticketswitch.discount import Discount

[
    TicketType(
        code='CIRCLE',
        description='Upper circle',
        price_bands=[
            PriceBand(
                code='A/pool',
                allows_leaving_single_seats='always',
                default_discount=Discount(
                    code='',
                    description='',
                    price_band_code='A/pool',
                    is_offer=False,
                    seatprice=35.0,
                    surcharge=4.0,
                    non_offer_seatprice=35.0,
                    non_offer_surcharge=4.0,
                    availability=6,
                    percentage_saving=0,
                    absolute_saving=0.0,
                ),
                example_seats_are_real=True,
                discounts=[
                    Discount(
                        code='ADULT',
                        description='Adult',
                        price_band_code='A/pool',
                        is_offer=False,
                        seatprice=35.0,
                        surcharge=4.0,
                        non_offer_seatprice=35.0,
                        non_offer_surcharge=4.0,
                        availability=6,
                        percentage_saving=0,
                        absolute_saving=0.0,
                    ),
                    Discount(
                        code='CHILD',
                        description='Child rate',
                        price_band_code='A/pool',
                        is_offer=False,
                        seatprice=18.0,
                        surcharge=3.0,
                        non_offer_seatprice=18.0,
                        non_offer_surcharge=3.0,
                        availability=6,
                        percentage_saving=0,
                        absolute_saving=0.0,
                    ),
                    Discount(
                        code='STUDENT',
                        description='Student rate',
                        price_band_code='A/pool',
                        is_offer=False,
                        seatprice=26.0,
                        surcharge=3.0,
                        non_offer_seatprice=26.0,
                        non_offer_surcharge=3.0,
                        availability=6,
                        percentage_saving=0,
                        absolute_saving=0.0,
                    ),
                    Discount(
                        code='OAP',
                        description='Senior citizen rate',
                        price_band_code='A/pool',
                        is_offer=False,
                        seatprice=28.0,
                        surcharge=3.0,
                        non_offer_seatprice=28.0,
                        non_offer_surcharge=3.0,
                        availability=6,
                        percentage_saving=0,
                        absolute_saving=0.0,
                    )
                ],
            ),
            PriceBand(
                code='B/pool',
                allows_leaving_single_seats='always',
                default_discount=Discount(
                    code='',
                    description='',
                    price_band_code='B/pool',
                    is_offer=False,
                    seatprice=30.0,
                    surcharge=4.0,
                    non_offer_seatprice=30.0,
                    non_offer_surcharge=4.0,
                    availability=6,
                    percentage_saving=0,
                    absolute_saving=0.0,
                ),
                example_seats_are_real=True,
                discounts=[
                    Discount(
                        code='ADULT',
                        description='Adult',
                        price_band_code='B/pool',
                        is_offer=False,
                        seatprice=30.0,
                        surcharge=4.0,
                        non_offer_seatprice=30.0,
                        non_offer_surcharge=4.0,
                        availability=6,
                        percentage_saving=0,
                        absolute_saving=0.0,
                    ),
                    Discount(
                        code='CHILD',
                        description='Child rate',
                        price_band_code='B/pool',
                        is_offer=False,
                        seatprice=15.0,
                        surcharge=3.0,
                        non_offer_seatprice=15.0,
                        non_offer_surcharge=3.0,
                        availability=6,
                        percentage_saving=0,
                        absolute_saving=0.0,
                    )
                ],
            ),
            PriceBand(
                code='C/pool',
                allows_leaving_single_seats='always',
                default_discount=Discount(
                    code='',
                    description='',
                    price_band_code='C/pool',
                    is_offer=False,
                    seatprice=25.0,
                    surcharge=4.0,
                    non_offer_seatprice=25.0,
                    non_offer_surcharge=4.0,
                    availability=6,
                    percentage_saving=0,
                    absolute_saving=0.0,
                ),
                example_seats_are_real=True,
                discounts=[
                    Discount(
                        code='ADULT',
                        description='Adult',
                        price_band_code='C/pool',
                        is_offer=False,
                        seatprice=25.0,
                        surcharge=4.0,
                        non_offer_seatprice=25.0,
                        non_offer_surcharge=4.0,
                        availability=6,
                        percentage_saving=0,
                        absolute_saving=0.0,
                    ),
                    Discount(
                        code='CHILD',
                        description='Child rate',
                        price_band_code='C/pool',
                        is_offer=False,
                        seatprice=13.0,
                        surcharge=3.0,
                        non_offer_seatprice=13.0,
                        non_offer_surcharge=3.0,
                        availability=6,
                        percentage_saving=0,
                        absolute_saving=0.0,
                    ),
                    Discount(
                        code='STUDENT',
                        description='Student rate',
                        price_band_code='C/pool',
                        is_offer=False,
                        seatprice=19.0,
                        surcharge=3.0,
                        non_offer_seatprice=19.0,
                        non_offer_surcharge=3.0,
                        availability=6,
                        percentage_saving=0,
                        absolute_saving=0.0,
                    ),
                    Discount(
                        code='OAP',
                        description='Senior citizen rate',
                        price_band_code='C/pool',
                        is_offer=False,
                        seatprice=20.0,
                        surcharge=3.0,
                        non_offer_seatprice=20.0,
                        non_offer_surcharge=3.0,
                        availability=6,
                        percentage_saving=0,
                        absolute_saving=0.0,
                    )
                ],
            )
        ],
    ),
    TicketType(
        code='STALLS',
        description='Stalls',
        price_bands=[
            PriceBand(
                code='A/pool',
                allows_leaving_single_seats='always',
                default_discount=Discount(
                    code='',
                    description='',
                    price_band_code='A/pool',
                    is_offer=False,
                    seatprice=21.0,
                    surcharge=3.0,
                    non_offer_seatprice=21.0,
                    non_offer_surcharge=3.0,
                    availability=6,
                    percentage_saving=0,
                    absolute_saving=0.0,
                ),
                example_seats_are_real=True,
                discounts=[
                    Discount(
                        code='ADULT',
                        description='Adult',
                        price_band_code='A/pool',
                        is_offer=False,
                        seatprice=21.0,
                        surcharge=3.0,
                        non_offer_seatprice=21.0,
                        non_offer_surcharge=3.0,
                        availability=6,
                        percentage_saving=0,
                        absolute_saving=0.0,
                    ),
                    Discount(
                        code='CHILD',
                        description='Child rate',
                        price_band_code='A/pool',
                        is_offer=False,
                        seatprice=11.0,
                        surcharge=2.0,
                        non_offer_seatprice=11.0,
                        non_offer_surcharge=2.0,
                        availability=6,
                        percentage_saving=0,
                        absolute_saving=0.0,
                    ),
                    Discount(
                        code='STUDENT',
                        description='Student rate',
                        price_band_code='A/pool',
                        is_offer=False,
                        seatprice=16.0,
                        surcharge=2.0,
                        non_offer_seatprice=16.0,
                        non_offer_surcharge=2.0,
                        availability=6,
                        percentage_saving=0,
                        absolute_saving=0.0,
                    ),
                    Discount(
                        code='OAP',
                        description='Senior citizen rate',
                        price_band_code='A/pool',
                        is_offer=False,
                        seatprice=17.0,
                        surcharge=2.0,
                        non_offer_seatprice=17.0,
                        non_offer_surcharge=2.0,
                        availability=6,
                        percentage_saving=0,
                        absolute_saving=0.0,
                    )
                ],
            ),
            PriceBand(
                code='B/pool',
                allows_leaving_single_seats='always',
                default_discount=Discount(
                    code='',
                    description='',
                    price_band_code='B/pool',
                    is_offer=False,
                    seatprice=18.0,
                    surcharge=3.0,
                    non_offer_seatprice=18.0,
                    non_offer_surcharge=3.0,
                    availability=3,
                    percentage_saving=0,
                    absolute_saving=0.0,
                ),
                example_seats_are_real=True,
                discounts=[
                    Discount(
                        code='ADULT',
                        description='Adult',
                        price_band_code='B/pool',
                        is_offer=False,
                        seatprice=18.0,
                        surcharge=3.0,
                        non_offer_seatprice=18.0,
                        non_offer_surcharge=3.0,
                        availability=3,
                        percentage_saving=0,
                        absolute_saving=0.0,
                    ),
                    Discount(
                        code='CHILD',
                        description='Child rate',
                        price_band_code='B/pool',
                        is_offer=False,
                        seatprice=9.0,
                        surcharge=2.0,
                        non_offer_seatprice=9.0,
                        non_offer_surcharge=2.0,
                        availability=3,
                        percentage_saving=0,
                        absolute_saving=0.0,
                    )
                ],
            )
        ],
    ),
    TicketType(
        code='BALCONY',
        description='Balcony',
        price_bands=[
            PriceBand(
                code='A/pool',
                allows_leaving_single_seats='always',
                default_discount=Discount(
                    code='',
                    description='',
                    price_band_code='A/pool',
                    is_offer=False,
                    seatprice=47.0,
                    surcharge=5.0,
                    non_offer_seatprice=47.0,
                    non_offer_surcharge=5.0,
                    availability=6,
                    percentage_saving=0,
                    absolute_saving=0.0,
                ),
                example_seats_are_real=True,
                discounts=[
                    Discount(
                        code='ADULT',
                        description='Adult',
                        price_band_code='A/pool',
                        is_offer=False,
                        seatprice=47.0,
                        surcharge=5.0,
                        non_offer_seatprice=47.0,
                        non_offer_surcharge=5.0,
                        availability=6,
                        percentage_saving=0,
                        absolute_saving=0.0,
                    ),
                    Discount(
                        code='CHILD',
                        description='Child rate',
                        price_band_code='A/pool',
                        is_offer=False,
                        seatprice=24.0,
                        surcharge=4.0,
                        non_offer_seatprice=24.0,
                        non_offer_surcharge=4.0,
                        availability=6,
                        percentage_saving=0,
                        absolute_saving=0.0,
                    ),
                    Discount(
                        code='STUDENT',
                        description='Student rate',
                        price_band_code='A/pool',
                        is_offer=False,
                        seatprice=35.0,
                        surcharge=4.0,
                        non_offer_seatprice=35.0,
                        non_offer_surcharge=4.0,
                        availability=6,
                        percentage_saving=0,
                        absolute_saving=0.0,
                    ),
                    Discount(
                        code='OAP',
                        description='Senior citizen rate',
                        price_band_code='A/pool',
                        is_offer=False,
                        seatprice=38.0,
                        surcharge=4.0,
                        non_offer_seatprice=38.0,
                        non_offer_surcharge=4.0,
                        availability=6,
                        percentage_saving=0,
                        absolute_saving=0.0,
                    )
                ],
            )
        ],
    )
]

The response includes a possible_discounts dictionary, that contains a list of discounts (or concessions) that are available on each price band. Each discount contains the same price band attributes that are returned in availability.

Discounts

Definition

GET https://api.ticketswitchswitch.com/f13/discounts.v1?perf_id={performanceid}&price_band_code={pricebandcode}&ticket_type_code={tickettypecode}

A discount represents a price type or concession that is available for a price band. These are some examples:

When retrieving availability for a performance we return the default discount. This discounts resource should then be used to get the full list of available discounts. When multiple discounts are returned non-default discounts typically have a lower price (for example Child pricing).

When multiple discounts are returned, you should present the choice to your user (we use a drop-down list). When there are multiple special offers available on a single ticket these are also presented as discounts so you can present the choice of special offer to your user (multiple offers are rare though). It is possible for you to ignore this call and just purchase the default discount even when there are multiple discounts, but that is not recommended.

Example request - price band

curl https://api.ticketswitchswitch.com/f13/discounts.v1 \
    -u "demo:demopass" \
    -d "perf_id=6IF-B0I" \
    -d "price_band_code=A/pool" \
    -d "ticket_type_code=CIRCLE" \
    --compressed \
    -G
from pyticketswitch import Client

client = Client('demo', 'demopass')
discounts, meta = client.get_discounts('6IF-B0O', 'STALLS', 'A/pool')

Request

Parameter Description
perf_id The performance identifier.
price_band_code The price band code you want to view discounts for.
ticket_type_code The ticket type code you want to view discounts for.
req_predicted_commission Optional. Include to retrieve commission data. For most partners this will include predicted_user_commission only (the predicted amount you earn per ticket). Some partners will also see predicted_gross_commission, which is the total commission available to be shared between Ingresso and our partner. By default you will see predicted_user_commission only - if you think you need to see predicted_gross_commission as well then please get in touch.
no_of_seats Optional. The number of tickets the customer would like. If this is specified then only discounts valid for the number of tickets will be shown.
promo_code Optional. If the supplier supports a promo code this can be specified to unlock a discount. This feature is not commonly used with partners.

Response

Example response

{
  "currency_code": "gbp",
  "currency_details": {
    "gbp": {
      "currency_code": "gbp",
      "currency_factor": 100,
      "currency_number": 826,
      "currency_places": 2,
      "currency_post_symbol": "",
      "currency_pre_symbol": "£"
    }
  },
  "discounts": {
    "discount": [
      {
        "absolute_saving": 0,
        "discount_code": "ADULT",
        "discount_desc": "Adult",
        "is_offer": false,
        "non_offer_sale_seatprice": 35,
        "non_offer_sale_surcharge": 4,
        "number_available": 6,
        "percentage_saving": 0,
        "price_band_code": "A/pool",
        "sale_seatprice": 35,
        "sale_surcharge": 4
      },
      {
        "absolute_saving": 0,
        "discount_code": "CHILD",
        "discount_desc": "Child rate",
        "is_offer": false,
        "non_offer_sale_seatprice": 18,
        "non_offer_sale_surcharge": 3,
        "number_available": 6,
        "percentage_saving": 0,
        "price_band_code": "A/pool",
        "sale_seatprice": 18,
        "sale_surcharge": 3
      },
      {
        "absolute_saving": 0,
        "discount_code": "STUDENT",
        "discount_desc": "Student rate",
        "is_offer": false,
        "non_offer_sale_seatprice": 26,
        "non_offer_sale_surcharge": 3,
        "number_available": 6,
        "percentage_saving": 0,
        "price_band_code": "A/pool",
        "sale_seatprice": 26,
        "sale_surcharge": 3
      },
      {
        "absolute_saving": 0,
        "discount_code": "OAP",
        "discount_desc": "Senior citizen rate",
        "is_offer": false,
        "non_offer_sale_seatprice": 28,
        "non_offer_sale_surcharge": 3,
        "number_available": 6,
        "percentage_saving": 0,
        "price_band_code": "A/pool",
        "sale_seatprice": 28,
        "sale_surcharge": 3
      }
    ]
  }
}
from pyticketswitch.discount import Discount

[
    Discount(
        code='ADULT',
        description='Adult',
        price_band_code='A/pool',
        is_offer=False,
        seatprice=21.0,
        surcharge=3.0,
        non_offer_seatprice=21.0,
        non_offer_surcharge=3.0,
        availability=6,
        percentage_saving=0,
        absolute_saving=0.0,
    ),
    Discount(
        code='CHILD',
        description='Child rate',
        price_band_code='A/pool',
        is_offer=False,
        seatprice=11.0,
        surcharge=2.0,
        non_offer_seatprice=11.0,
        non_offer_surcharge=2.0,
        availability=6,
        percentage_saving=0,
        absolute_saving=0.0,
    ),
    Discount(
        code='STUDENT',
        description='Student rate',
        price_band_code='A/pool',
        is_offer=False,
        seatprice=16.0,
        surcharge=2.0,
        non_offer_seatprice=16.0,
        non_offer_surcharge=2.0,
        availability=6,
        percentage_saving=0,
        absolute_saving=0.0,
    ),
    Discount(
        code='OAP',
        description='Senior citizen rate',
        price_band_code='A/pool',
        is_offer=False,
        seatprice=17.0,
        surcharge=2.0,
        non_offer_seatprice=17.0,
        non_offer_surcharge=2.0,
        availability=6,
        percentage_saving=0,
        absolute_saving=0.0,
    )
]

The following attributes are returned within the discount dictionary. These are the same attributes returned in the availability price band dictionary.

Attribute Description
absolute_saving Defined as (non_offer_sale_seatprice + non_offer_sale_surcharge) - (sale_seatprice + sale_surcharge)
discount_code The unique identifier of the discount. This is unique to each supplier system, so you cannot assume that if the “ADULT” discount_code is available on one event that it will be available on other events.
discount_desc The description of the default discount to present to users.
is_offer true if the ticket price is discounted below the full price, i.e. if absolute_saving is greater than zero.
non_offer_sale_seatprice The per-ticket price for full-priced tickets. This will be the face value price when the market has such a concept (for example the London theatre market has this concept, but some New York theatre shows do not). This is the same as the sale_seatprice when the price band is not discounted.
non_offer_sale_surcharge The per-ticket booking fee for full-priced tickets. To determine the total ticket price you must add together the non_offer_sale_seatprice and the non_offer_sale_surcharge.
number_available This is the maximum number of contiguous seats that can be purchased. This applies to best available only - if you are using seat selection and contiguous_seat_selection_only is false it is possible to select above this number.
percentage_saving Defined as absolute_saving / (non_offer_sale_seatprice + non_offer_sale_surcharge) * 100
price_band_code The code for a price band. To uniquely identify a price band you should take the combination of ticket_type_code and price_band_code.
price_band_desc The description for the price band. This will often not be present (not all supplier ticketing systems provide it) but when it is present it should be displayed to the customer.
sale_seatprice The per-ticket price. This will be the face value price when the market has such a concept (for example the London theatre market has this concept, but some New York theatre shows do not). This is the same as the non_offer_sale_seatprice when the price band is not discounted.
sale_surcharge The per-ticket booking fee. To determine the total ticket price you must add together the sale_seatprice and the sale_surcharge.

The outer object also includes a currency_code and a currency_details object containing further currency detail:

Attribute Description
currency_code ISO 4217 three letter code
currency_factor Multiply by this number to get values in the base unit (e.g. multiplying $47.11 by the currency_factor will give 4711 cents)
currency_number ISO 4217 numeric identifier
currency_places The number of decimal places to display (eg 45.5 usd should be displayed as 45.50)
currency_post_symbol A symbol to display at the end of the price
currency_pre_symbol A symbol to display in front of the price

Send Methods

GET https://api.ticketswitch.com/f13/send_methods.v1?perf_id={performanceid}

This section describes the available methods of delivery for a given performance. Each method in the list has an associated cost which will be added to the overall charge.

Send methods might change between performances and depending on times when they are requested. For example there might not be enough time to post a physical ticket to a customer before the performance starts, so those performances would not have that option available. As such it’s important that send methods are called as needed to ensure the user isn’t seeing options that are out of date.

Example request

curl https://api.ticketswitch.com/f13/send_methods.v1 \
    -u "demo:demopass" \
    -d "perf_id=6IF-B0I" \
    --compressed \
    -G
from pyticketswith import Client

client = Client('demo', 'demopass')
send_methods, meta = client.get_send_methods('6IF-B0O')

Request

Parameter Description
perf_id The performance identifier that you want to display send methods for.

Example response

{
  "currency_code": "gbp",
  "currency_details": {
    "gbp": {
      "currency_code": "gbp",
      "currency_factor": 100,
      "currency_number": 826,
      "currency_places": 2,
      "currency_post_symbol": "",
      "currency_pre_symbol": "£"
    }
  },
  "send_methods": {
    "send_method": [
      {
        "send_code": "COBO",
        "send_cost": 1.5,
        "send_desc": "Collect from the venue",
        "send_type": "collect"
      },
      {
        "permitted_countries": {
          "country": [
            {
              "country_code": "ie",
              "country_desc": "Ireland"
            },
            {
              "country_code": "uk",
              "country_desc": "United Kingdom"
            }
          ]
        },
        "send_code": "POST",
        "send_cost": 3.5,
        "send_desc": "Post (UK & Ireland only)",
        "send_type": "post",
        "send_final_comment": "Please allow 3 working days to recieve your tickets."
      }
    ]
  }
}
from pyticketswitch.country import Country
from pyticketswitch.send_method import SendMethod

[
    SendMethod(
        code='COBO',
        cost=1.5,
        description='Collect from the venue',
        type='collect',
    ),
    SendMethod(
        code='POST',
        cost=3.5,
        description='Post (UK & Ireland only)',
        type='post',
        final_comment='Please allow 3 working days to receive your tickets.'
        permitted_countries=[
            Country(
                code='ie',
                description='Ireland',
            ),
            Country(
                code='uk',
                description='United Kingdom',
            )
        ],
    )
]

Response

Attribute Description
send_code The identifier of this send method.
send_cost Any additional cost that the customer will have to pay if they chose this send method.
send_desc A human readable description of the send method.
send_final_comment A human readable string containing information about posting times.
send_type Can be collect which indicates that the ticket will have to be collected in person, either at the venue or from a confirmation email. A type of post indicates that a physical ticket will be posted to the delivery address given at purchase time.
permitted_countries If this is returned it indicates that the send method is only available to addresses in the listed countries.
permitted_countries.country_code 2-digit country code (using ISO 3166-1 alpha-2).
permitted_countries.country_description Human readable description of the country.

The outer object also includes a currency_code and a currency_details object containing further currency detail:

Attribute Description
currency_code ISO 4217 three letter code
currency_factor Multiply by this number to get values in the base unit (e.g. multiplying $47.11 by the currency_factor will give 4711 cents)
currency_number ISO 4217 numeric identifier
currency_places The number of decimal places to display (eg 45.5 usd should be displayed as 45.50)
currency_post_symbol A symbol to display at the end of the price
currency_pre_symbol A symbol to display in front of the price

Trolley

Definition

GET https://api.ticketswitch.com/f13/trolley.v1

A trolley allows multiple orders to be purchased in a single transaction.

If you only plan to purchase a single order at a time then there is no need to use a trolley - you should instead go straight to reserve.

The trolley itself should be considered a wish list. No tickets are reserved until the reserve call is made. Having a ticket in a trolley is not a guarantee that the ticket will still be available when you attempt to reserve the tickets.

Trolleys are identified by a trolley_token, which is simply a hash of the orders in the trolley. Every time a change is made to the trolley the hash changes and so does the trolley_token. An individual trolley_token is therefore an identifier for the current state of your trolley, and can not be used to identify your trolley as you add or remove orders.

Request

Example request - adding best available tickets to a new trolley, specifying specific discount codes

curl https://api.ticketswitch.com/f13/trolley.v1 \
    -u "demo:demopass" \
    -d "perf_id=6IF-B1S" \
    -d "ticket_type_code=CIRCLE" \
    -d "price_band_code=C/pool" \
    -d "no_of_seats=3" \
    -d "disc0=ADULT" \
    -d "disc1=CHILD" \
    -d "disc2=CHILD" \
    --compressed \
    -G
from pyticketswitch import Client

client = Client('demo', 'demopass')
trolley, meta = client.get_trolley(
    performance_id='6IF-B0O',
    number_of_seats=2,
    price_band_code='A/pool',
    ticket_type_code='STALLS'
)

Example request - adding specific seats to an existing trolley

curl https://api.ticketswitch.com/f13/trolley.v1 \
    -u "demo:demopass" \
    -d "trolley_token=eTxD00cZU3ON_j1-lBBoshxPyWY6yaCmb-pMcqlk-jeh1lAc3XnbK8l3eTuhGw9GH9rNfeTuvLcd-NQfLdZxOpibtG3g_4E5ssrtUcZErxA5Er0kcCZHKvKjTPhuRY49j3mWYZivbGGIo9bh7ASnQBNIEkl98SXjzH_hy3w16p95Zb9Tbfat0Iq5CtE7SKFgZhXTaq5zzBPDB5aqhTEAzR87BahqzoIkHRnKylxRZbxYvqZyglaJ5j1HdisF8vDZLUKCb8h4mErsUvOirXXQBLMjglD1RgQQqYGc3bZc6pXrlmOOLWyKiPv97-Nnvu7I8laXEQevemDcJWiz3W-SwV-qhbPQj9NwT3lPWzoHnR_iTT6fAWRex_LTHXCRqs65IzXqsJrLlkzuO5E1k9WQJMpk0Jkj2Zinc3WjWPZZUOBNnAhWk1bSE1FUbd0UVsq0zr8MqX3td5vzwmaiWvgRTFs5MOM2aR6BAfWKmbnV7QLgMJCC-GCP2Rm4mwb5IxyhCWTEaosblz5zDEQuqqnPpWiOtt3qXMIxe0G7UTesRA2b42JIN9tmYc9Pn5x5Apd7MggfkrPX1ulS9kA4JPMkI6U-.Z" \
    -d "perf_id=7AB-5" \
    -d "ticket_type_code=STALLS" \
    -d "price_band_code=A/pool" \
    -d "no_of_seats=2" \
    -d "seat0=A1" \
    -d "seat1=A2" \
    --compressed \
    -G
from pyticketswitch import Client

client = Client('demo', 'demopass')
trolley, meta = client.get_trolley(
    trolley_token='PcCSFHBD2pd49k5mYjpoBHjE25O7isjAQkGMqZF15oHLa0W0q-UDnwrAtc6aKmNsOnSBMD77u76gdqqgfJLwnWw6RRKjKJhRHiE0GgG0dN4RYdSTP3Hrw9lix6pj-mZ2m9vLF6tTZAUMTi0HjEc2s9MLo6xu2eVvg4zPKNZ0mr_MllWtiWRc4zMt-RDZy0QEqGb9mcA0GPbNJh3pnRd2Q5_ZgBJ21n8rSgTiKYj02AztAcfF8LcHVTPuldaCgyE_VHxZyW9djxPORTLBiPytBoPURku7bd5kn2w9XeXoHocsODU2yWJpPLrikKqGNHU13uH2LewpbOEnueFi4SVxUxZTG53pN_1tJ-nI3XtGGOHvWvnhode94YB-OJ2xnKy1R6P_OYq1uFH-vRl7fgXNwXdEzfu0yrf-4YLwahQKVUIxrdyswF6XYd-7PoBU3Aj1dDfbEXbm96l8JqKxiHTUM7U-.Z',
    performance_id='7AB-5',
    ticket_type_code='STALLS',
    price_band_code='A/pool',
    number_of_seats=2,
    seats=['A1', 'A2'],
)

Example request - view the current state of the trolley

curl https://api.ticketswitch.com/f13/trolley.v1 \
    -u "demo:demopass" \
    -d "trolley_token=eTxD00cZU3ON_j1-lBBoshxPyWY6yaCmb-pMcqlk-jeh1lAc3XnbK8l3eTuhGw9GH9rNfeTuvLcd-NQfLdZxOpibtG3g_4E5ssrtUcZErxA5Er0kcCZHKvKjTPhuRY49j3mWYZivbGGIo9bh7ASnQBNIEkl98SXjzH_hy3w16p95Zb9Tbfat0Iq5CtE7SKFgZhXTaq5zzBPDB5aqhTEAzR87BahqzoIkHRnKylxRZbxYvqZyglaJ5j1HdisF8vDZLUKCb8h4mErsUvOirXXQBLMjglD1RgQQqYGc3bZc6pXrlmOOLWyKiPv97-Nnvu7I8laXEQevemDcJWiz3W-SwV-qhbPQj9NwT3lPWzoHnR_iTT6fAWRex_LTHXCRqs65IzXqsJrLlkzuO5E1k9WQJMpk0Jkj2Zinc3WjWPZZUOBNnAhWk1bSE1FUbd0UVsq0zr8MqX3td5vzwmaiWvgRTFs5MOM2aR6BAfWKmbnV7QLgMJCC-GCP2Rm4mwb5IxyhCWTEaosblz5zDEQuqqnPpWiOtt3qXMIxe0G7UTesRA2b42JIN9tmYc9Pn5x5Apd7MggfkrPX1ulS9kA4JPMkI6U-.Z" \
    --compressed \
    -G
from pyticketswitch import Client

client = Client('demo', 'demopass')
trolley, meta = client.get_trolley(
    token='PcCSFHBD2pd49k5mYjpoBHjE25O7isjAQkGMqZF15oHLa0W0q-UDnwrAtc6aKmNsOnSBMD77u76gdqqgfJLwnWw6RRKjKJhRHiE0GgG0dN4RYdSTP3Hrw9lix6pj-mZ2m9vLF6tTZAUMTi0HjEc2s9MLo6xu2eVvg4zPKNZ0mr_MllWtiWRc4zMt-RDZy0QEqGb9mcA0GPbNJh3pnRd2Q5_ZgBJ21n8rSgTiKYj02AztAcfF8LcHVTPuldaCgyE_VHxZyW9djxPORTLBiPytBoPURku7bd5kn2w9XeXoHocsODU2yWJpPLrikKqGNHU13uH2LewpbOEnueFi4SVxUxZTG53pN_1tJ-nI3XtGGOHvWvnhode94YB-OJ2xnKy1R6P_OYq1uFH-vRl7fgXNwXdEzfu0yrf-4YLwahQKVUIxrdyswF6XYd-7PoBU3Aj1dDfbEXbm96l8JqKxiHTUM7U-.Z',
)

Example request - removing the first order from the trolley

curl https://api.ticketswitch.com/f13/trolley.v1 \
    -u "demo:demopass" \
    -d "trolley_token=eTxD00cZU3ON_j1-lBBoshxPyWY6yaCmb-pMcqlk-jeh1lAc3XnbK8l3eTuhGw9GH9rNfeTuvLcd-NQfLdZxOpibtG3g_4E5ssrtUcZErxA5Er0kcCZHKvKjTPhuRY49j3mWYZivbGGIo9bh7ASnQBNIEkl98SXjzH_hy3w16p95Zb9Tbfat0Iq5CtE7SKFgZhXTaq5zzBPDB5aqhTEAzR87BahqzoIkHRnKylxRZbxYvqZyglaJ5j1HdisF8vDZLUKCb8h4mErsUvOirXXQBLMjglD1RgQQqYGc3bZc6pXrlmOOLWyKiPv97-Nnvu7I8laXEQevemDcJWiz3W-SwV-qhbPQj9NwT3lPWzoHnR_iTT6fAWRex_LTHXCRqs65IzXqsJrLlkzuO5E1k9WQJMpk0Jkj2Zinc3WjWPZZUOBNnAhWk1bSE1FUbd0UVsq0zr8MqX3td5vzwmaiWvgRTFs5MOM2aR6BAfWKmbnV7QLgMJCC-GCP2Rm4mwb5IxyhCWTEaosblz5zDEQuqqnPpWiOtt3qXMIxe0G7UTesRA2b42JIN9tmYc9Pn5x5Apd7MggfkrPX1ulS9kA4JPMkI6U-.Z" \
    -d "remove_items_list=1" \
    --compressed \
    -G
from pyticketswitch import Client

client = Client('demo', 'demopass')
trolley, meta = client.get_trolley(
    token='PcCSFHBD2pd49k5mYjpoBHjE25O7isjAQkGMqZF15oHLa0W0q-UDnwrAtc6aKmNsOnSBMD77u76gdqqgfJLwnWw6RRKjKJhRHiE0GgG0dN4RYdSTP3Hrw9lix6pj-mZ2m9vLF6tTZAUMTi0HjEc2s9MLo6xu2eVvg4zPKNZ0mr_MllWtiWRc4zMt-RDZy0QEqGb9mcA0GPbNJh3pnRd2Q5_ZgBJ21n8rSgTiKYj02AztAcfF8LcHVTPuldaCgyE_VHxZyW9djxPORTLBiPytBoPURku7bd5kn2w9XeXoHocsODU2yWJpPLrikKqGNHU13uH2LewpbOEnueFi4SVxUxZTG53pN_1tJ-nI3XtGGOHvWvnhode94YB-OJ2xnKy1R6P_OYq1uFH-vRl7fgXNwXdEzfu0yrf-4YLwahQKVUIxrdyswF6XYd-7PoBU3Aj1dDfbEXbm96l8JqKxiHTUM7U-.Z',
    item_numbers_to_remove=[1, 2, 3],   
)

The single trolley call is used for multiple use cases such as:

Note that adding an order will remove anything in the trolley which would prevent it being added. Removed orders are listed as discarded_orders. The common reasons why two orders cannot sit alongside each other are:

Also note that when adding individual seats to a trolley, there are restrictions on the seats that can be added in a single order:

If you would like to allow your customers to select seats without restriction across price bands and ticket types, you need to add multiple orders to a trolley, one order for each ticket type / price band. However there are currently some restrictions enforced so if you want to do this you will need to contact us first

Parameter Description
discX Specify a discount code for ticket number X, with zero-based numbering (so to specify the CHILD discount code on the second ticket use disc1=CHILD). Note that illegal discount codes are replaced with legal ones.
no_of_seats The number of tickets you want to add to the trolley. It is optional to specify discount codes, however note that if you choose to specify them you must specify all of them. If you do not specify discount codes you will receive the default discount code - this will match what you are shown when you request availability.
perf_id The performance identifier for the tickets that you want to add to your trolley.
price_band_code The price band identifier for the tickets that you want to add to your trolley.
remove_items_list A comma separated list of order item_numbers that were previously added to the trolley and that you now want to remove.
seatX Specify a specific seat for ticket number X, with zero-based numbering (so to specify seat A12 as the first ticket use seat0=A12). If seat numbers are not specified then when the trolley is later reserved you will receive best available tickets.
X_send_code Specify a send / despatch method for supplier system X. If this is not present it will default to the first send method. For example, to specify the POST send method for the nimax supplier system, use nimax_send_code=POST.
ticket_type_code The ticket type identifier for the tickets that you want to add to your trolley.
trolley_token The identifier for the trolley. This is used to add additional orders to a trolley, or to remove orders in a trolley.
req_predicted_commission Optional. Include to retrieve commission data. For most partners this will include predicted_user_commission only (the predicted amount you earn per ticket). Some partners will also see predicted_gross_commission, which is the total commission available to be shared between Ingresso and our partner. By default you will see predicted_user_commission only - if you think you need to see predicted_gross_commission as well then please get in touch.

Additional parameters, primarily for internal use:

Parameter Description
add_crypto_block cypto_blocks are used in the old Ingresso XML API. To make migration away from the XML API easier, if you include add_crypto_block a crypto_block will be added to the response. You can then take the crypto_block and trolley_token and pass these in to the XML API call make_reservation to reserve and later purchase tickets (so that the JSON API is used up to the basket stage and the XML API is used to complete the purchase).
departure_date Specify a departure date for example departure_date=20170214.
duration Specify a duration for hotel product, for example duration=3.
promo_code Specifying a promo codes can unlock a special offer discount code. If you have a promo code it can be specified like this: promo_code=FOO. Note that this feature is not commonly used with partners.

All of the following parameters can also be used to request additional data for the event and performance in each order. These are described in more detail in the Events section here.

Parameter Description
req_avail_details Returns availability details - a cached list of unique ticket types and price bands available for the event and performance in each order. This parameter is not commonly used.
req_avail_details_with_perfs This will add the list of available performance dates to each avail detail object. Only valid if used alongside req_avail_details.
req_cost_range Returns cost ranges - a from price and offer detail for the event and performance in each order.
req_cost_range_best_value_offer Returns the offer with the highest percentage saving.
req_cost_range_details Returns a list of unique ticket types and price bands and their cost ranges across all performances. This parameter is not commonly used.
req_cost_range_max_saving_offer Returns the offer with the highest absolute saving.
req_cost_range_min_cost_offer Returns the offer with the lowest cost.
req_cost_range_top_price_offer Returns the offer with the highest cost. This is the least used offer cost range.
req_cost_range_no_singles_data This returns another cost range object that excludes availability with only 1 consecutive seat available. The prices in this cost range will therefore be the same or higher than the outer cost range. It has the same structure as the main cost range (so if you want to see the “best value offer” in the no singles data, you need to add req_cost_range_best_value_offer and you will see this data in both cost ranges).
req_extra_info Returns the descriptive info for the event, returned as individual sections (structured_info) or as a single summary (event_info / event_info_html).
req_media_triplet_one Triplet one (jpg/png 520x390). See further detail on media.
req_media_triplet_two Triplet two if available (jpg/png 520x390).
req_media_triplet_three Triplet three if available (jpg/png 520x390).
req_media_triplet_four Triplet four if available (jpg/png 520x390).
req_media_triplet_five Triplet five if available (jpg/png 520x390).
req_media_seating_plan Graphical seating plan of the venue if available (jpg/png varying size).
req_media_square Small square image suitable for search or event avatar (jpg/png 140x140).
req_media_landscape Small landscape banner suitable for search (jpg/png 220x115).
req_media_marquee Large landscape banner suitable for a page heading, if available (jpg/png 700x300).
req_media_supplier Logo of the supplier/producer, if available (jpg/png varying size).
req_reviews Returns event reviews if available.
req_video_iframe Returns video iframe information if available.

Response

Example response - adding specific seats to an existing trolley

{
  "currency_details": {
    "gbp": {
      "currency_code": "gbp",
      "currency_factor": 100,
      "currency_number": 826,
      "currency_places": 2,
      "currency_post_symbol": "",
      "currency_pre_symbol": "£"
    }
  },
  "discarded_orders": [],
  "trolley_token": "k5--2fvf6Qc19ceQa4b9Kx4zIhDezG2yPzN71dEUmA8r3qFFCJJAQ3M3kYft_h9rzMAEBYyT0yNdS31HOv2WuYMbAbC8i49reKFaUu3esJckOm4cDipyTgQy3iekje0zgEM0MBSx1XY6t5bgbQ170iNxU2CLjUmZAT9K5iyqI-PN3hmJEpj0s5NMb31-THH8ufud82Mh2TeBP_c_e3_sabim1ftOfrnS6qPQAo9DF-Z1gXIXKLIzqCozRUwKqSOyLKbwAgfJSMi_2fQ_MhWMNkldjrfbOPpM0qKReJm8wPVW_zZNL_px_Mmg8LEIMgd5soJAa1edNePTrvSLppbDkevea-9Lr9UWERYKoSVXCsLSaEw2dGqaNJggpU6S_ksyduog3ALwStTJ6dr8dyGY5mImdVNcZhRepdmvKbRYNzBTDSxxY2n2LefoJkxc8bg-FxPacE9DRRNY_ZPl7f3fpa4a0Oq8j2DfrGxVcw0McxLoQ1E8XUkAH99LztF0qZN9RYuFwpQhoomgNOROf2M03DigA59j5ipO4Mg8p3iLKVndHJXS1SJfItBt1h86VXXUg0pkeZGn1e6TQkwx9m6t5faz4zuzGEg8XpuOXBxBqHrvQOFaFY5tDYYGr4x-uM2VowFCpM2c3-Aal3EeyjChHTycW---Z",
  "trolley_token_contents": {
    "bundle": [
      {
        "bundle_order_count": 1,
        "bundle_source_code": "ext_test0",
        "bundle_source_desc": "External Test Backend 0",
        "bundle_total_cost": 52.5,
        "bundle_total_seatprice": 51,
        "bundle_total_send_cost": 1.5,
        "bundle_total_surcharge": 0,
        "currency_code": "gbp",
        "order": [
          {
            "event": {
              "city_code": "london-uk",
              "city_desc": "London",
              "classes": {
                "dance": "Ballet & Dance"
              },
              "country_code": "uk",
              "country_desc": "United Kingdom",
              "critic_review_percent": 100,
              "custom_filter": [],
              "event_desc": "Matthew Bourne's Nutcracker TEST",
              "event_id": "6IF",
              "event_path": "/6IF-matthew-bourne-s-nutcracker-test/",
              "event_status": "live",
              "event_type": "simple_ticket",
              "event_upsell_list": {
                "event_id": [
                  "6IE",
                  "MH0"
                ]
              },
              "event_uri_desc": "Matthew-Bourne%27s-Nutcracker-TEST",
              "geo_data": {
                "latitude": 51.52961137,
                "longitude": -0.10601562
              },
              "has_no_perfs": false,
              "is_seated": true,
              "max_running_time": 120,
              "min_running_time": 120,
              "need_departure_date": false,
              "need_duration": false,
              "need_performance": true,
              "postcode": "EC1R 4TN",
              "show_perf_time": true,
              "source_code": "ext_test0",
              "source_desc": "External Test Backend 0",
              "user_review_percent": 100,
              "venue_desc": "Sadler's Wells",
              "venue_uri_desc": "Sadler%27s-Wells"
            },
            "got_requested_seats": false,
            "item_number": 1,
            "performance": {
              "date_desc": "Sun, 15th January 2017",
              "event_id": "6IF",
              "has_pool_seats": false,
              "is_ghost": true,
              "is_limited": false,
              "iso8601_date_and_time": "2017-01-15T19:30:00Z",
              "perf_id": "6IF-A7N",
              "time_desc": "7.30 PM"
            },
            "price_band_code": "C/pool",
            "ticket_orders": {
              "ticket_order": [
                {
                  "discount_code": "ADULT",
                  "discount_desc": "Adult standard",
                  "no_of_seats": 1,
                  "sale_seatprice": 25,
                  "sale_surcharge": 0,
                  "total_sale_seatprice": 25,
                  "total_sale_surcharge": 0
                },
                {
                  "discount_code": "CHILD",
                  "discount_desc": "Child rate",
                  "no_of_seats": 2,
                  "sale_seatprice": 13,
                  "sale_surcharge": 0,
                  "total_sale_seatprice": 26,
                  "total_sale_surcharge": 0
                }
              ]
            },
            "ticket_type_code": "CIRCLE",
            "ticket_type_desc": "Upper circle",
            "total_no_of_seats": 3,
            "total_sale_seatprice": 51,
            "total_sale_surcharge": 0
          }
        ]
      },
      {
        "bundle_order_count": 1,
        "bundle_source_code": "ext_test1",
        "bundle_source_desc": "External Test Backend 1",
        "bundle_total_cost": 110,
        "bundle_total_seatprice": 100,
        "bundle_total_send_cost": 0,
        "bundle_total_surcharge": 10,
        "currency_code": "gbp",
        "order": [
          {
            "event": {
              "city_code": "london-uk",
              "city_desc": "London",
              "classes": {
                "theatre": "Theatre"
              },
              "country_code": "uk",
              "country_desc": "United Kingdom",
              "custom_filter": [],
              "event_desc": "The Unremarkable Incident of the Cat at Lunchtime",
              "event_id": "7AB",
              "event_path": "/7AB-the-unremarkable-incident-of-the-cat-at-lunchtime/",
              "event_status": "live",
              "event_type": "simple_ticket",
              "event_uri_desc": "The-Unremarkable-Incident-of-the-Cat-at-Lunchtime",
              "geo_data": {
                "latitude": 51.49306,
                "longitude": -0.22639
              },
              "has_no_perfs": false,
              "is_seated": true,
              "max_running_time": 90,
              "min_running_time": 90,
              "need_departure_date": false,
              "need_duration": false,
              "need_performance": true,
              "postcode": "W6 7ES",
              "show_perf_time": true,
              "source_code": "ext_test1",
              "source_desc": "External Test Backend 1",
              "venue_desc": "Lyric Apollo",
              "venue_uri_desc": "Lyric-Apollo"
            },
            "got_requested_seats": true,
            "item_number": 2,
            "performance": {
              "date_desc": "Tue, 1st January 2019",
              "event_id": "7AB",
              "has_pool_seats": true,
              "is_ghost": false,
              "is_limited": false,
              "iso8601_date_and_time": "2019-01-01T15:30:00Z",
              "perf_id": "7AB-5",
              "running_time": 90,
              "time_desc": "3.30 PM"
            },
            "price_band_code": "A/pool",
            "requested_seats": [
              {
                "col_id": "1",
                "full_id": "A1",
                "is_restricted_view": true,
                "row_id": "A",
                "seat_text": "Restricted View",
                "seat_text_code": "A.1"
              },
              {
                "col_id": "2",
                "full_id": "A2",
                "is_restricted_view": true,
                "row_id": "A",
                "seat_text": "Restricted View",
                "seat_text_code": "A.2"
              }
            ],
            "ticket_orders": {
              "ticket_order": [
                {
                  "discount_code": "NORMAL",
                  "discount_desc": "Regular Ticket",
                  "no_of_seats": 2,
                  "sale_seatprice": 50,
                  "sale_surcharge": 5,
                  "total_sale_seatprice": 100,
                  "total_sale_surcharge": 10
                }
              ]
            },
            "ticket_type_code": "STALLS",
            "ticket_type_desc": "Stalls",
            "total_no_of_seats": 2,
            "total_sale_seatprice": 100,
            "total_sale_surcharge": 10
          }
        ]
      }
    ],
    "trolley_bundle_count": 2,
    "trolley_order_count": 2
  }
}
from pyticketswitch.event import Event
from pyticketswitch.bundle import Bundle
from pyticketswitch.performance import Performance
from pyticketswitch.order import TicketOrder
from pyticketswitch.trolley import Trolley
from pyticketswitch.order import Order

Trolley(
    token='64--QVkNGtT6STKmvXGI1e3mnxGkt-myQ56VW_cMlAxai766x2C-ksxcll2pY7-AUFsdyzNivWoVuCVJUwUfaiSFUUPQN6ErqZeAM5hRX6KXIHy4eLuzeV6SX8PvZDsO0RScIwO54SNFcgIPHl9MEnl0F_amE0EPNPSqn7C9IZqBkERKUfoi-E9eysQlq-EiQUKZPxev24rAS9ASDZPkpQKY4-9zM-fF1DSLcic0uho5c3jFsajf8QTrD_Se9sUfy4OrATwTIVmRZXNyeTFZWTJji0HQg3HmATR5Xhe_BzuOwqvxLjyT65uEP3oStqo3RZ6o1HiMe3DxI9u5khAf3QrIrd0-3bS4JsAmm5JQiq_Vg2FqfJTf42Gipre9kcU8mnAVHjPvGgNyGpuG2fQHpTCd-Pd9jiDbC93ckOJ8DZN8FJZbbYWD82Ep_w90YlSug5uQ_vh2f54xgD2RQRyxpyTAeKegBI-YRtiolLgSnGfuVyFCWb0JHES4ZrQHBEuii5gnocURfBq9sL--Z',
    bundles=[
        Bundle(
            source_code='ext_test0',
            orders=[
                Order(
                    item=1,
                    event=Event(
                        id='6IF',
                        status='live',
                        description="Matthew Bourne's Nutcracker TEST",
                        source='External Test Backend 0',
                        source_code='ext_test0',
                        event_type='simple_ticket',
                        venue="Sadler's Wells",
                        classes={
                            'dance': 'Ballet & Dance'
                        },
                        postcode='EC1R 4TN',
                        city='London',
                        city_code='london-uk',
                        country='United Kingdom',
                        country_code='uk',
                        latitude=51.52961137,
                        longitude=-0.10601562,
                        max_running_time=120,
                        min_running_time=120,
                        show_performance_time=True,
                        has_performances=True,
                        is_seated=True,
                        needs_departure_date=False,
                        needs_duration=False,
                        needs_performance=False,
                        upsell_list=[
                            '6IE',
                            'MH0'
                        ],
                        critic_review_percent=100,
                    ),
                    performance=Performance(
                        id='6IF-B0O',
                        event_id='6IF',
                        date_time=datetime.datetime(2017, 5, 4, 19, 30, tzinfo=tzoffset(None, 3600)),
                        date_description='Thu, 4th May 2017',
                        time_description='7.30 PM',
                        has_pool_seats=True,
                        is_limited=False,
                        is_ghost=False,
                        running_time=120,
                    ),
                    price_band_code='A/pool',
                    ticket_type_code='STALLS',
                    ticket_type_description='Stalls',
                    ticket_orders=[
                        TicketOrder(
                            code='',
                            description='',
                            number_of_seats=2,
                            seatprice=21.0,
                            surcharge=3.0,
                            total_seatprice=42.0,
                            total_surcharge=6.0,
                        )
                    ],
                    number_of_seats=2,
                    total_seatprice=42.0,
                    total_surcharge=6.0,
                    requested_seat_ids=[

                    ],
                )
            ],
            description='External Test Backend 0',
            total_seatprice=42.0,
            total_surcharge=6.0,
            total_send_cost=1.5,
            total=49.5,
            currency_code='gbp',
        ),
        Bundle(
            source_code='ext_test1',
            orders=[
                Order(
                    item=2,
                    event=Event(
                        id='7AB',
                        status='live',
                        description='The Unremarkable Incident of the Cat at Lunchtime',
                        source='External Test Backend 1',
                        source_code='ext_test1',
                        event_type='simple_ticket',
                        venue='Lyric Apollo',
                        classes={
                            'theatre': 'Theatre'
                        },
                        postcode='W6 7ES',
                        city='London',
                        city_code='london-uk',
                        country='United Kingdom',
                        country_code='uk',
                        latitude=51.49306,
                        longitude=-0.22639,
                        max_running_time=90,
                        min_running_time=90,
                        show_performance_time=True,
                        has_performances=True,
                        is_seated=True,
                        needs_departure_date=False,
                        needs_duration=False,
                        needs_performance=False,
                    ),
                    performance=Performance(
                        id='7AB-5',
                        event_id='7AB',
                        date_time=datetime.datetime(2019, 1, 1, 15, 30, tzinfo=tzutc()),
                        date_description='Tue, 1st January 2019',
                        time_description='3.30 PM',
                        has_pool_seats=True,
                        is_limited=False,
                        is_ghost=False,
                        running_time=90,
                    ),
                    price_band_code='A/pool',
                    ticket_type_code='STALLS',
                    ticket_type_description='Stalls',
                    ticket_orders=[
                        TicketOrder(
                            code='NORMAL',
                            description='Regular Ticket',
                            number_of_seats=2,
                            seatprice=50.0,
                            surcharge=5.0,
                            total_seatprice=100.0,
                            total_surcharge=10.0,
                        )
                    ],
                    number_of_seats=2,
                    total_seatprice=100.0,
                    total_surcharge=10.0,
                    requested_seat_ids=[
                        'A1',
                        'A2'
                    ],
                )
            ],
            description='External Test Backend 1',
            total_seatprice=100.0,
            total_surcharge=10.0,
            total_send_cost=0.0,
            total=110.0,
            currency_code='gbp',
        )
    ],
)

The trolley has three main structures:

trolley attributes:

Attribute Description
discarded_orders As discussed above, adding an order will remove anything in the trolley which would prevent it being added. See below for detail of the order object.
input_contained_unavailable_order This is a flag that will get set to true if part of the trolley request could not be added to the trolley. This occurs when we weren’t able to find any available products that matched the request and it usually means the user has passed in invalid parameters or is requesting an item that is sold out.
trolley_token_contents See below for object detail.
trolley_token The identifier for the trolley (this is an internal hash representing the items in the trolley, so the identifier will be the same for identical trolleys).

trolley_token_contents attributes:

Attribute Description
bundle See below for object detail.
trolley_bundle_count The number of bundles in the trolley.
trolley_order_count The number of orders in the trolley. There will be at least one order for every bundle.

bundle attributes

Attribute Description
bundle_order_count The number of orders in this bundle.
bundle_source_code The code of the supplier system that this bundle will be purchased from.
bundle_source_desc The name of the supplier system that this bundle will be purchased from.
bundle_total_cost The total cost of this bundle.
bundle_total_seatprice The total face value for this bundle.
bundle_total_send_cost The despatch cost for this bundle (similar to a transaction fee). Orders within the same bundle will be sent together.
bundle_total_surcharge The total booking fee for this bundle.
currency_code The currency code for the price - further detail for the currency can be found in the currency_details object, described below.
order See below for object detail.

order attributes:

Attribute Description
event The event for this order.
item_number A unique sequential number for the order. The second order added to the trolley will have item_number 2. The item_number remains constant as orders are added or removed, so if item_number 1 is removed, the first order will be item_number 2.
performance The performance for this order.
price_band_code The code for a price band, for example “C/pool”. The price band code is generally made up of the code from the underlying supplier system, e.g. “C”, followed by a “/” separator then “pool” or “alloc”, indicating whether the price band is taken from the general pool of tickets or is from a ring-fenced allocation.
seat_request_status The status of your tickets after they have been reserved. Possible values are not_requested (specific seats not requested), got_none (you requested A13 and A14 but we gave you A15 and A16), got_partial (you requested A13 and A14 but we gave you A14 and A15), got_all (you requested A13 and A14 and you got A13 and A14 - by far the most common response when requesting specific seats).
ticket_orders A number of ticket_order objects, details below.
ticket_type_code The unique identifier for the ticket type. For attractions this can refer to variations such as General Admission or Fast Track, and there is often only only. For seated events this normally refers to a part of house / seating area such as Grand Circle.
ticket_type_desc The description for the ticket type. This should be displayed to the customer
total_no_of_seats The number of tickets for this order.
total_sale_seatprice The total face value for this order.
total_sale_surcharge The total booking fee for this order.

ticket_order attributes:

Attribute Description
discount_code The discount code that applies to this ticket_order.
discount_desc The description for the discount code.
no_of_seats The number of tickets in this ticket_order.
sale_seatprice The face value per ticket in this ticket_order.
sale_surcharge The booking fee per ticket in this ticket_order.
total_sale_seatprice The total face value of all tickets in this ticket_order.
total_sale_surcharge The total booking fee of all tickets in this ticket_order.

The outer object includes a currency_details object containing one currency object (indexed on the currency code) for every currency referenced in the JSON response. Each currency has the following attributes:

Attribute Description
currency_code ISO 4217 three letter code
currency_factor Multiply by this number to get values in the base unit (e.g. multiplying $47.11 by the currency_factor will give 4711 cents)
currency_number ISO 4217 numeric identifier
currency_places The number of decimal places to display (eg 45.5 usd should be displayed as 45.50)
currency_post_symbol A symbol to display at the end of the price
currency_pre_symbol A symbol to display in front of the price

Add-ons

Add-ons are items that can only be purchased alongside a normal event, for example The Lion King could have add-ons for ticket insurance, a Simba toy and a restaurant nearby the Lyceum Theatre.

Add-ons can only be added to a trolley already containing tickets for an event containing add-ons.

Definition

GET https://api.ticketswitch.com/f13/add_ons.v1

This resource returns detail for which add-on events may be added to a given trolley. The trolley token must be specified, or the parameters required to build a valid trolley must be specified, or both. This call is nullipotent, and will not change the state of any existing trolley.

Request

Example request

curl https://api.ticketswitch.com/f13/add_ons.v1 \
    -u "demo:demopass" \
    -d "trolley_token=M2--6TcZRZsfgZI0E8PmlGWqr5PQluhxE46Nqnno3Xa24lFuIKM_0IYJq40BDvisBRcXKsaGBdLfu8B5TfwI4s7jk7y7xRto_SwJL177u_vuvvq_Ynqnj64IfAHmItXxz_-xdTQGXh_G-BuPGxPXNY_Ycimiv1ZYlPFuPjsoVugnUnyu2F0TmpdztEtgI9PC1WhnTeHeRUDEBvVewOIf_PEJkPVR-UXFDg3gxbHYQBENW5XpkYnRhc22IqrB7eAoK0MbTLaPMk3uB1BKnz_B7fasSU_NU3nhXvmgHa4suvCT9oEaQSGvq4G0glOtyCiqL1FfVJ2R3KIgb2xC4NbAm4cNL5q22V_W0eYGmJ9DTBJ90UWvAWH7UeFLM1--Z" \
    --compressed \
    -G
from pyticketswitch import Client

client = Client(user='demo', password='demopass')
addon_events, addon_meta = client.get_addons(token="M2--6TcZRZsfgZI0E8PmlGWqr5PQluhxE46Nqnno3Xa24lFuIKM_0IYJq40BDvisBRcXKsaGBdLfu8B5TfwI4s7jk7y7xRto_SwJL177u_vuvvq_Ynqnj64IfAHmItXxz_-xdTQGXh_G-BuPGxPXNY_Ycimiv1ZYlPFuPjsoVugnUnyu2F0TmpdztEtgI9PC1WhnTeHeRUDEBvVewOIf_PEJkPVR-UXFDg3gxbHYQBENW5XpkYnRhc22IqrB7eAoK0MbTLaPMk3uB1BKnz_B7fasSU_NU3nhXvmgHa4suvCT9oEaQSGvq4G0glOtyCiqL1FfVJ2R3KIgb2xC4NbAm4cNL5q22V_W0eYGmJ9DTBJ90UWvAWH7UeFLM1--Z")

Either the trolley_token parameter, and/or a valid set of parameters for a trolley call must be supplied.

Parameter Description
trolley_token A valid identifier for an existing trolley.
——— ———–
discX A trolley with a discount code for added tickets.
no_of_seats A trolley with a specified number of tickets added.
perf_id A trolley with tickets for the specified performance added.
price_band_code A trolley with tickets from the specified price band added.
remove_items_list A trolley with the specified item_numbers removed.
seatX A trolley with the specified seat ID added as one of the tickets.
X_send_code A trolley with the specified send method for new tickets added.
ticket_type_code A trolley with tickets of the specified ticket type added.

The list of optional additional parameters specified can also be included and will add the details to the response.

Response

Example response

{
  "results": {
    "event": [
      {
        "city_code": "london-uk",
        "city_desc": "London",
        "classes": {
          "theatre": "Theatre"
        },
        "country_code": "uk",
        "country_desc": "United Kingdom",
        "custom_filter": [],
        "event_desc": "Unremarkable Cat Lunchbox",
        "event_id": "7AC",
        "event_path": "/7AC-unremarkable-cat-lunchbox/",
        "event_status": "live",
        "event_type": "misc_item",
        "event_uri_desc": "Unremarkable-Cat-Lunchbox",
        "geo_data": {
          "latitude": 51.49306,
          "longitude": -0.22639
        },
        "has_no_perfs": false,
        "is_add_on": true,
        "is_auto_quantity_add_on": true,
        "is_seated": false,
        "need_departure_date": false,
        "need_duration": false,
        "need_performance": false,
        "postcode": "W6 7ES",
        "show_perf_time": false,
        "source_code": "ext_test1",
        "source_desc": "External Test Backend 1",
        "venue_desc": "Lyric Apollo",
        "venue_uri_desc": "Lyric-Apollo"
      }
    ],
    "paging_status": {
      "page_length": 50,
      "page_number": 0,
      "pages_remaining": 0,
      "results_remaining": 0,
      "total_unpaged_results": 1
    }
  }
}
from pyticketswitch.event import Event

[
    Event(
        min_running_time=None,
        event_type=u'misc_item',
        has_performances=True,
        venue_info_html=None,
        critic_review_percent=None,
        needs_departure_date=False,
        valid_quantities=None,
        addon_events=None,
        availability_details=[],
        postcode=u'W6 7ES',
        country_code=u'uk',
        id=u'7AC',
        city=u'London',
        filters=[],
        media={},
        is_seated=False,
        upsell_events=None,
        event_info=None,
        content={},
        source=u'External Test Backend 1',
        max_running_time=None,
        cost_range_details=[],
        needs_performance=False,
        latitude=51.49306,
        upsell_list=[],
        city_code=u'london-uk',
        venue_addr=None,
        status=u'live',
        description=u'Unremarkable Cat Lunchbox',
        venue_addr_html=None,
        cost_range=None,
        event_info_html=None,
        source_code=u'ext_test1',
        country=u'United Kingdom',
        venue_info=None,
        venue=u'Lyric Apollo',
        longitude=-0.22639,
        is_add_on=True,
        is_auto_quantity_add_on=True,
        reviews=[],
        classes={
            u'theatre': u'Theatre'
        },
        fields={},
        needs_duration=False,
        no_singles_cost_range=None,
        component_events=[],
        show_performance_time=False,
    )
]

The format of the response is identical to that of the events list.

Attribute Description
city_code Code of the city where the event is taking place.
city_desc Name of the city where the event is taking place.
classes A collection of categories (a.k.a. “classes”) that this event belongs to. The index is the class code, the value is the class description.
country_code 2-digit country code (using ISO 3166-1 alpha-2)
country_desc Name of the country where the event is taking place.
critic_review_percent The aggregate critic review score, e.g. 80 for 80%.
custom_filter Array of custom filter codes. This can be ignored by partners.
event_desc Name of the show or event e.g. The Lion King.
event_id Unique identifier for the event.
event_path If you also use a white label website this can be used to navigate to the event page, e.g. /2J5V-la-pedrera-skip-the-line/.
event_status Will be live for a normal event search. Other values are dead and pending but these will only be displayed when using the include_dead or include_non_live parameters.
event_type Currently all events are of type simple_ticket. In future we may add hotel_room and misc_item.
geo_data A block containing the following geo co-ordinates:
geo_data.latitude Latitude of the event.
geo_data.longitude Longitude of the event.
has_no_perfs true if the event has no performances. For example some attraction tickets are valid for any date, so we do not present a list of performances to select.
is_add_on false if this event is an add-on event. This means it can only be added to a trolley containing tickets for an event that lists this in its add_ons.
is_auto_quantity_add_on false Indicates whether add on quantity will be modified based on the number of ticket orders, if true number of addons will be equal to total number of tickets for all parent events in the trolley.
is_seated true for seated events.
max_running_time Maximum length / duration in minutes (not always present).
min_running_time Minimum length / duration in minutes (not always present).
need_departure_date Flag indicating whether the event needs a departure date specified. This is false for most events. Most partners can ignore this.
need_duration Flag indicating whether the event needs duration (specific to hotel_room events only). Most partners can ignore this.
need_performance Flag indicating if a performance must be selected in order to retrieve availability. For the vast majority of events this will be true.
postcode Postcode of the event location.
show_perf_time false if the performance time is not relevant, for example some events use a performance description rather than specific times.
source_code Source supplier code e.g. nimax.
source_desc Source supplier description e.g. Nimax.
user_review_percent The aggregate user review score, e.g. 80 for 80%.
venue_desc Name of the venue e.g. Sadler's Wells.
venue_uri_desc URI encoded name of the venue e.g. Sadler%27s-Wells.

The outer object also contains a paging_status object:

Attribute Description
page_length The number of results per page.
page_number The zero-based page number currently displayed.
pages_remaining The number of pages that you need to request after the current page to retrieve all results.
results_remaining The number of results in the remaining pages.
total_unpaged_results The total number of results.

Reserve

Definition

POST https://api.ticketswitch.com/f13/reserve.v1

Before purchasing tickets, you must first reserve them. Reserving tickets will put them on hold for a period of time, ensuring they cannot be purchased by anyone else until you explicitly release them or until the hold time expires when the tickets are automatically released. Reserve is typically called immediately before displaying a checkout page to customers to collect contact details. These details are then used as parameters when purchasing the reservation.

There are two main use cases for calling reserve:

  1. You only want to purchase a single order at a time: call reserve with a perf_id, ticket_type_code, price_band_code, no_of_seats, and other optional parameters if necessary.

  2. You want to purchase multiple orders in a single transaction: first add orders to your trolley, then reserve the trolley by specifying a trolley_token.

As with trolley there are restrictions on reserving individual seats:

If you would like to allow your customers to select seats without restriction across price bands and ticket types, you need to add multiple orders to a trolley, one order for each ticket type / price band. However there are currently some restrictions enforced so if you want to do this you will need to contact us first.

Request

Example request - reserving best available tickets, specifying specific discount codes

curl https://api.ticketswitch.com/f13/reserve.v1 \
    -u "demo:demopass" \
    -d "perf_id=6IF-B1S" \
    -d "ticket_type_code=CIRCLE" \
    -d "price_band_code=C/pool" \
    -d "no_of_seats=3" \
    -d "disc0=ADULT" \
    -d "disc1=CHILD" \
    -d "disc2=CHILD" \
    --compressed \
    -X POST
from pyticketswitch import Client

client = Client('demo', 'demopass')
reservation, meta = client.make_reservation(
    performance_id='6IF-A7N',
    ticket_type_code='CIRCLE',
    price_band_code='C/pool',
    number_of_seats=3,
    discounts=['ADULT', 'CHILD', 'CHILD']
)

Example request - reserving specific seats

curl https://api.ticketswitch.com/f13/reserve.v1 \
    -u "demo:demopass" \
    -d "perf_id=7AB-5" \
    -d "ticket_type_code=STALLS" \
    -d "price_band_code=A/pool" \
    -d "no_of_seats=2" \
    -d "seat0=A1" \
    -d "seat1=A2" \
    --compressed \
    -X POST
from pyticketswitch import Client

client = Client('demo', 'demopass')
reservation, meta = client.make_reservation(
    performance_id='7AB-5',
    ticket_type_code='STALLS',
    price_band_code='A/pool',
    number_of_seats=2,
    seats=['A1', 'A2']
)

Example request - reserving orders previously added to a trolley

curl https://api.ticketswitch.com/f13/reserve.v1 \
    -u "demo:demopass" \
    -d "trolley_token=s2--pFMaAzbxn3wG3zY-OAuclGgU9zzsUFJOLXpOquDKNGpwGn205i4_XzD6O6i8ZCqo2qxmA5QdvETbr7DlqTsbLayzHrvvf9zrz2NdGZuggwXHdx3cgPdbJzFeexIylGsxo7d3T9FWUkViv76Rz7qUH8qXeb9nWjF7ahrNsuHA8w_R63XmOQVNDIvJFS1hC6vFO3sD3t0MqKKguqRWuP4mM2vRN6BimgWYqrNqQw5D_-bfumE1Xl2vXu3FgSEp_N9dpsQ1fXK3qfoOiH-Hsd0F2Zh84IyMcrJkGZH8dlhdEWbvaMlu1rQ8Kw6hJMUigc31jbfHjuquCpDgI-OKyV8LQuQGz8wZsxj3jwWmLClcl50W7p1dTVLEYIW52jWqALRYFAresEGqzct0xDCeaoAjZ5vagMS2KXVmZ" \
    --compressed \
    -X POST
from pyticketswitch import Client

client = Client('demo', 'demopass')
reservation, meta = client.make_reservation(
    token='s2--pFMaAzbxn3wG3zY-OAuclGgU9zzsUFJOLXpOquDKNGpwGn205i4_XzD6O6i8ZCqo2qxmA5QdvETbr7DlqTsbLayzHrvvf9zrz2NdGZuggwXHdx3cgPdbJzFeexIylGsxo7d3T9FWUkViv76Rz7qUH8qXeb9nWjF7ahrNsuHA8w_R63XmOQVNDIvJFS1hC6vFO3sD3t0MqKKguqRWuP4mM2vRN6BimgWYqrNqQw5D_-bfumE1Xl2vXu3FgSEp_N9dpsQ1fXK3qfoOiH-Hsd0F2Zh84IyMcrJkGZH8dlhdEWbvaMlu1rQ8Kw6hJMUigc31jbfHjuquCpDgI-OKyV8LQuQGz8wZsxj3jwWmLClcl50W7p1dTVLEYIW52jWqALRYFAresEGqzct0xDCeaoAjZ5vagMS2KXVmZ'
)

Note that the request parameters and response attributes are similar to trolley.

Parameter Description
discX Specify a discount code for ticket number X, with zero-based numbering (so to specify the CHILD discount code on the second ticket use disc1=CHILD). Note that illegal discount codes are replaced with legal ones. It is optional to specify discount codes, however note that if you choose to specify them you must specify all of them. If you do not specify discount codes you will receive the default discount code - this will match what you are shown when you request availability.
no_of_seats The number of tickets you want to reserve.
perf_id The performance identifier for the tickets that you want to reserve.
price_band_code The price band identifier for the tickets that you want to reserve.
remove_items_list A comma separated list of order item_numbers that you want to remove from the trolley before reserving.
seatX Specify a specific seat for ticket number X, with zero-based numbering (so to specify seat A12 as the first ticket use seat0=A12). If seat numbers are not specified then you will receive best available seats.
X_send_code Specify a send / despatch method for supplier system X. If this is not present it will default to the first send method. For example, to specify the POST send method for the nimax supplier system, use nimax_send_code=POST.
ticket_type_code The ticket type identifier for the tickets that you want to add to your trolley.
trolley_token The identifier for a trolley. This is used to reserve multiple items at once.
req_predicted_commission Optional. Include to retrieve commission data. For most partners this will include predicted_user_commission only (the predicted amount you earn per ticket). Some partners will also see predicted_gross_commission, which is the total commission available to be shared between Ingresso and our partner. By default you will see predicted_user_commission only - if you think you need to see predicted_gross_commission as well then please get in touch.

Additional parameters, primarily for internal use:

Parameter Description
departure_date Specify a departure date for example departure_date=20170214.
duration Specify a duration for hotel product, for example duration=3.
promo_code Specifying a promo codes can unlock a special offer discount code. If you have a promo code it can be specified like this: promo_code=FOO. Note that this feature is not commonly used with partners.

All of the following parameters can also be used to request additional data for the event and performance in each order. These are described in more detail in the Events section here.

Parameter Description
req_avail_details Returns availability details - a cached list of unique ticket types and price bands available for the event and performance in each order. This parameter is not commonly used.
req_avail_details_with_perfs This will add the list of available performance dates to each avail detail object. Only valid if used alongside req_avail_details.
req_cost_range Returns cost ranges - a from price and offer detail for the event and performance in each order.
req_cost_range_best_value_offer Returns the offer with the highest percentage saving.
req_cost_range_details Returns a list of unique ticket types and price bands and their cost ranges across all performances. This parameter is not commonly used.
req_cost_range_max_saving_offer Returns the offer with the highest absolute saving.
req_cost_range_min_cost_offer Returns the offer with the lowest cost.
req_cost_range_top_price_offer Returns the offer with the highest cost. This is the least used offer cost range.
req_cost_range_no_singles_data This returns another cost range object that excludes availability with only 1 consecutive seat available. The prices in this cost range will therefore be the same or higher than the outer cost range. It has the same structure as the main cost range (so if you want to see the “best value offer” in the no singles data, you need to add req_cost_range_best_value_offer and you will see this data in both cost ranges).
req_extra_info Returns the descriptive info for the event, returned as individual sections (structured_info) or as a single summary (event_info / event_info_html).
req_media_triplet_one Triplet one (jpg/png 520x390). See further detail on media.
req_media_triplet_two Triplet two if available (jpg/png 520x390).
req_media_triplet_three Triplet three if available (jpg/png 520x390).
req_media_triplet_four Triplet four if available (jpg/png 520x390).
req_media_triplet_five Triplet five if available (jpg/png 520x390).
req_media_seating_plan Graphical seating plan of the venue if available (jpg/png varying size).
req_media_square Small square image suitable for search or event avatar (jpg/png 140x140).
req_media_landscape Small landscape banner suitable for search (jpg/png 220x115).
req_media_marquee Large landscape banner suitable for a page heading, if available (jpg/png 700x300).
req_media_supplier Logo of the supplier/producer, if available (jpg/png varying size).
req_reviews Returns event reviews if available.
req_video_iframe Returns video iframe information if available.

Response

Example response - reserving orders previously added to a trolley

{
  "allowed_countries": {
    "ad": "Andorra",
    "ae": "United Arab Emirates",
    "af": "Afghanistan",
    "ag": "Antigua and Barbuda",
    ....
    "uk": "United Kingdom",
    "um": "The United States Minor Outlying Islands",
    "us": "United States of America",
    "uy": "Uruguay"
  },
  "can_edit_address": true,
  "currency_details": {
    "gbp": {
      "currency_code": "gbp",
      "currency_factor": 100,
      "currency_number": 826,
      "currency_places": 2,
      "currency_post_symbol": "",
      "currency_pre_symbol": "£"
    }
  },
  "minutes_left_on_reserve": 15,
  "needs_agent_reference": false,
  "needs_email_address": false,
  "needs_payment_card": false,
  "prefilled_address": {
    "country_code": "uk"
  },
  "trolley_contents": {
    "bundle": [
      {
        "bundle_order_count": 1,
        "bundle_source_code": "ext_test0",
        "bundle_source_desc": "External Test Backend 0",
        "bundle_total_cost": 76.5,
        "bundle_total_seatprice": 75,
        "bundle_total_send_cost": 1.5,
        "bundle_total_surcharge": 0,
        "currency_code": "gbp",
        "order": [
          {
            "event": {
              "city_code": "london-uk",
              "city_desc": "London",
              "classes": {
                "dance": "Ballet & Dance"
              },
              "country_code": "uk",
              "country_desc": "United Kingdom",
              "critic_review_percent": 100,
              "custom_filter": [],
              "event_desc": "Matthew Bourne's Nutcracker TEST",
              "event_id": "6IF",
              "event_path": "/6IF-matthew-bourne-s-nutcracker-test/",
              "event_status": "live",
              "event_type": "simple_ticket",
              "event_upsell_list": {
                "event_id": [
                  "6IE",
                  "MH0"
                ]
              },
              "event_uri_desc": "Matthew-Bourne%27s-Nutcracker-TEST",
              "geo_data": {
                "latitude": 51.52961137,
                "longitude": -0.10601562
              },
              "has_no_perfs": false,
              "is_seated": true,
              "max_running_time": 120,
              "min_running_time": 120,
              "need_departure_date": false,
              "need_duration": false,
              "need_performance": true,
              "postcode": "EC1R 4TN",
              "show_perf_time": true,
              "source_code": "ext_test0",
              "source_desc": "External Test Backend 0",
              "user_review_percent": 100,
              "venue_desc": "Sadler's Wells",
              "venue_uri_desc": "Sadler%27s-Wells"
            },
            "got_requested_seats": false,
            "item_number": 1,
            "performance": {
              "date_desc": "Tue, 13th June 2017",
              "event_id": "6IF",
              "has_pool_seats": true,
              "is_ghost": false,
              "is_limited": false,
              "iso8601_date_and_time": "2017-06-13T19:30:00+01:00",
              "perf_id": "6IF-B1S",
              "perf_name": "Including back stage pass",
              "running_time": 120,
              "time_desc": "7.30 PM"
            },
            "price_band_code": "C/pool",
            "send_method": {
              "send_code": "COBO",
              "send_cost": 1.5,
              "send_desc": "Collect from the venue",
              "send_type": "collect"
            },
            "ticket_orders": {
              "ticket_order": [
                {
                  "discount_code": "ADULT",
                  "discount_desc": "Adult",
                  "no_of_seats": 3,
                  "sale_seatprice": 25,
                  "sale_surcharge": 0,
                  "seats": [
                    {
                      "col_id": "424",
                      "full_id": "GL424",
                      "is_restricted_view": false,
                      "row_id": "GL"
                    },
                    {
                      "col_id": "421",
                      "full_id": "GL421",
                      "is_restricted_view": false,
                      "row_id": "GL"
                    },
                    {
                      "col_id": "418",
                      "full_id": "GL418",
                      "is_restricted_view": false,
                      "row_id": "GL"
                    }
                  ],
                  "total_sale_seatprice": 75,
                  "total_sale_surcharge": 0
                }
              ]
            },
            "ticket_type_code": "CIRCLE",
            "ticket_type_desc": "Upper circle",
            "total_no_of_seats": 3,
            "total_sale_seatprice": 75,
            "total_sale_surcharge": 0
          }
        ]
      }
    ],
    "transaction_uuid": "e18c20fc-042e-11e7-975c-002590326962",
    "trolley_bundle_count": 1,
    "trolley_order_count": 1
  },
  "unreserved_orders": []
}
from pyticketswitch.send_method import SendMethod
from pyticketswitch.country import Country
from pyticketswitch.seat import Seat
from pyticketswitch.address import Address
from pyticketswitch.event import Event
from pyticketswitch.bundle import Bundle
from pyticketswitch.performance import Performance
from pyticketswitch.reservation import Reservation
from pyticketswitch.order import TicketOrder
from pyticketswitch.trolley import Trolley
from pyticketswitch.order import Order

Reservation(
    status='reserved',
    reserved_at=datetime.datetime(2017, 5, 3, 15, 1, 45, tzinfo=tzutc()),
    trolley=Trolley(
        transaction_uuid='6d080a78-3011-11e7-b228-0025903268dc',
        bundles=[
            Bundle(
                source_code='ext_test1',
                orders=[
                    Order(
                        item=1,
                        event=Event(
                            id='7AB',
                            status='live',
                            description='The Unremarkable Incident of the Cat at Lunchtime'
,
                            source='External Test Backend 1',
                            source_code='ext_test1',
                            event_type='simple_ticket',
                            venue='Lyric Apollo',
                            classes={
                                'theatre': 'Theatre'
                            },
                            postcode='W6 7ES',
                            city='London',
                            city_code='london-uk',
                            country='United Kingdom',
                            country_code='uk',
                            latitude=51.49306,
                            longitude=-0.22639,
                            max_running_time=90,
                            min_running_time=90,
                            show_performance_time=True,
                            has_performances=True,
                            is_seated=True,
                            needs_departure_date=False,
                            needs_duration=False,
                            needs_performance=False,
                        ),
                        performance=Performance(
                            id='7AB-5',
                            event_id='7AB',
                            date_time=datetime.datetime(2019, 1, 1, 15, 30, tzinfo=tzutc()) ,
                            date_description='Tue, 1st January 2019',
                            time_description='3.30 PM',
                            has_pool_seats=True,
                            is_limited=False,
                            is_ghost=False,
                            running_time=90,
                        ),
                        price_band_code='A/pool',
                        ticket_type_code='STALLS',
                        ticket_type_description='Stalls',
                        ticket_orders=[
                            TicketOrder(
                                code='NORMAL',
                                seats=[
                                    Seat(
                                        id='A1',
                                        column='1',
                                        row='A',
                                        separator='',
                                        is_restricted=True,
                                        seat_text='Restricted View',
                                    ),
                                    Seat(
                                        id='A2',
                                        column='2',
                                        row='A',
                                        separator='',
                                        is_restricted=True,
                                        seat_text='Restricted View',
                                    )
                                ],
                                description='Regular Ticket',
                                number_of_seats=2,
                                seatprice=50.0,
                                surcharge=5.0,
                                total_seatprice=100.0,
                                total_surcharge=10.0,
                            )
                        ],
                        number_of_seats=2,
                        total_seatprice=100.0,
                        total_surcharge=10.0,
                        seat_request_status='got_all',
                        requested_seat_ids=[
                            'A1',
                            'A2'
                        ],
                        send_method=SendMethod(
                            code='VOUCH',
                            cost=0.0,
                            description='Printable eTicket',
                            type='selfprint',
                            can_generate_self_print=False,
                        ),
                    )
                ],
                description='External Test Backend 1',
                total_seatprice=100.0,
                total_surcharge=10.0,
                total_send_cost=0.0,
                total=110.0,
                currency_code='gbp',
            )
        ],
        minutes_left=14.9833333333,
    ),
    languages=[
        'en'
    ],
    needs_payment_card=False,
    needs_email_address=False,
    needs_agent_reference=False,
    can_edit_address=True,
    allowed_countries=[
        Country(
            code='uk',
            description='United Kingdom',
        )
    ],
    minutes_left=14.9833333333,
)

Example response - one order - reserved failed

{
    "input_contained_unavailable_order": false,
    "unreserved_orders": [
        {
            "event": {
                "city_code": "london-uk",
                "city_desc": "London",
                "classes": {
                    "theatre": "Theatre"
                },
                "country_code": "uk",
                "country_desc": "United Kingdom",
                "custom_filter": [],
                "event_desc": "TEST EVENT - The Unremarkable Incident of the Cat at Lunchtime",
                "event_id": "7AB",
                "event_path": "/7AB-test-event-the-unremarkable-incident-of-the-cat-at-lunchtime/",
                "event_status": "live",
                "event_type": "simple_ticket",
                "event_upsell_list": {
                    "event_id": [
                        "7AA",
                        "6IF"
                    ]
                },
                "event_uri_desc": "TEST-EVENT-The-Unremarkable-Incident-of-the-Cat-at-Lunchtime",
                "geo_data": {
                    "latitude": 51.49306,
                    "longitude": -0.22639
                },
                "has_no_perfs": false,
                "is_add_on": false,
                "is_auto_quantity_add_on": false,
                "is_date_matched_add_on": false,
                "is_seated": true,
                "is_time_matched_add_on": false,
                "need_departure_date": false,
                "need_duration": false,
                "need_performance": true,
                "postcode": "W6 7ES",
                "show_perf_time": true,
                "source_code": "ext_test1",
                "source_desc": "External Test Backend 1",
                "venue_desc": "Lyric Apollo",
                "venue_uri_desc": "Lyric-Apollo"
            },
            "internal_reserve_sub_ref": "",
            "internal_reserve_sub_ref2": "",
            "item_number": 1,
            "performance": {
                "date_desc": "Sun, 1st January 2023",
                "event_id": "7AB",
                "has_pool_seats": true,
                "is_ghost": false,
                "is_limited": false,
                "iso8601_date_and_time": "2023-01-01T15:30:00Z",
                "perf_id": "7AB-9",
                "time_desc": "3.30 PM"
            },
            "price_band_code": "B/pool",
            "requested_seat_ids": [
                "H9",
                "H10"
            ],
            "reserve_failure_comment": "Seat H10 causes failure.",
            "seat_request_status": "got_none",
            "send_method": {
                "can_generate_self_print": false,
                "has_html_page": true,
                "send_code": "VOUCH",
                "send_cost": 0.0,
                "send_desc": "Printable E-Ticket (Test)",
                "send_type": "selfprint"
            },
            "ticket_orders": {
                "ticket_order": [
                    {
                        "discount_code": "NORMAL",
                        "discount_desc": "Regular Ticket",
                        "discount_semantic_type": "standard",
                        "no_of_seats": 2,
                        "sale_combined": 35.0,
                        "sale_seatprice": 30.0,
                        "sale_surcharge": 5.0,
                        "total_sale_combined": 70.0,
                        "total_sale_seatprice": 60.0,
                        "total_sale_surcharge": 10.0
                    }
                ]
            },
            "ticket_type_code": "CIRCLE",
            "ticket_type_desc": "Dress Circle",
            "total_no_of_seats": 2,
            "total_sale_combined": 70.0,
            "total_sale_seatprice": 60.0,
            "total_sale_surcharge": 10.0
        }
    ]
}

The response will include an identifier for the reserve, detail of the reserved items, detail of items that weren’t able to be reserved, and a set of flags that confirm the information you need to collect from your customer when purchasing tickets.

Attribute Description
accepted_payment_cards This should not be present for partners and can be ignored.
allowed_countries A list of country codes and human-readable descriptions. The country codes are ISO 3166-1 alpha-2 codes. This list is relevant when selecting a despatch method that is restricted to certain countries, for example a local post despatch method may only be available in the supplier’s country. These are typically presented to customers in a dropdown list on a checkout page. The customer’s country code is a required parameter when purchasing tickets.
can_edit_address Indicates whether it is possible to change the non-blank prefilled_address data. This is primarily for internal use and can be ignored for normal use cases (it only applies to partners who have asked to have a prefilled address held in the Ingresso system). In most cases this will be true. If it is false the non-blank prefilled_address fields will be used when tickets are purchased and we will ignore the values in these fields if they are passed to us.
input_contained_unavailable_order This is a flag that will get set to true if part of the reservation request could not be reserved. This occurs when we weren’t able to find any available products that matched the request and it usually means the user has passed in invalid parameters or is requesting an item that is sold out.
needs_agent_reference For the vast majority of partners this will be false and can be ignored. However some partners ask to require that they specify their own reference when purchasing tickets - if this is true then the reference must be passed in.
needs_email_address If true you must pass in an email address when purchasing tickets. We recommend that you always send us the customer’s email address. We guarantee to only use this if our customer service team need to contact your customer in an emergency or if our supplier needs to directly email confirmation to your customer (this is not used for any events as at Jan 2017, but is possible in future). If you cannot send the customer’s email address then we recommend that you don’t send an email address if needs_email_address is false; if it is true then send an internal email address (for example your customer service email address) and it will be your responsibility to contact the customer or pass on booking confirmation.
needs_payment_card This will be false for all partners so can be ignored. If this is true you need to collect card details from the customer and include them when purchasing.
prefilled_address Some partners will have an address already held in the Ingresso system which should be prefilled for the user (by default this will not be enabled for partners - you will need to explicitly request it). The non-blank fields below should be prefilled. can_edit_address indicates whether the user can edit any of the prefilled fields.
prefilled_address.address_line_one The first line of the address - if this is non-blank it should be prefilled.
prefilled_address.address_line_two The second line of the address - if this is non-blank it should be prefilled.
prefilled_address.country_code The country code of the address - if this is non-blank it should be prefilled.
prefilled_address.email_address The email address - if this is non-blank it should be prefilled.
prefilled_address.home_phone The home phone - if this is non-blank it should be prefilled.
prefilled_address.postcode The postcode / zip code - if this is non-blank it should be prefilled.
prefilled_address.town The town - if this is non-blank it should be prefilled.
prefilled_address.work_phone The work phone - if this is non-blank it should be prefilled.
trolley_contents See below for object detail.
supports_billing_address For the vast majority of partners this can be ignored (it isn’t relevant to partners who purchase on-credit). When it is true a separate address may be provided when purchasing tickets, and this will be used to validate the payment card address for venue systems that perform address verification checks.
unreserved_orders A list of orders that could not be reserved.

trolley_contents attributes:

Attribute Description
bundle See below for object detail.
minutes_left_on_reserve A numeric representation of the number of minutes that your reserve will be held open for. For example, 12.5 is 12 minutes and 30 seconds.
transaction_uuid The unique reference for this reservation. This is needed for any further interactions with the reservation.
trolley_bundle_count The number of bundles in the trolley.
trolley_order_count The number of orders in the trolley. There will be at least one order for every bundle.

As explained in more detail in trolley, a trolley contains three nested objects:

If you only plan to reserve a single item at a time then a successful reserve will contain a single order within a single bundle.

bundle attributes

Attribute Description
bundle_order_count The number of orders in this bundle.
bundle_source_code The code of the supplier system that this bundle will be purchased from.
bundle_source_desc The name of the supplier system that this bundle will be purchased from.
bundle_total_cost The total cost of this bundle.
bundle_total_cost_in_desired The total cost of this bundle, converted to your desired_currency. This field will not be present for most partners.
bundle_total_seatprice The total face value for this bundle.
bundle_total_seatprice_in_desired The total face value for this bundle, converted to your desired_currency. This field will not be present for most partners.
bundle_total_send_cost The despatch cost for this bundle (similar to a transaction fee). Orders within the same bundle will be sent together.
bundle_total_send_cost_in_desired The despatch cost for this bundle, converted to your desired_currency. This field will not be present for most partners.
bundle_total_surcharge The total booking fee for this bundle.
bundle_total_surcharge_in_desired The total booking fee for this bundle, converted to your desired_currency. This field will not be present for most partners.
currency_code The currency code for the price - further detail for the currency can be found in the currency_details object, described below.
debitor_choices A list of debitors. See below for object detail.
desired_currency_code Most partners will not see a desired_currency_code, but it is possible for a partner to request to always view prices in a specific currency. For example if a product is supplied in GBP, but your desired_currency_code is set to USD, we will return prices in GBP along with _desired prices in USD. If you are taking payment using Ingresso’s Stripe connection, then payment will be taken in the default currency (GBP, in the example), and if you are being invoiced by Ingresso we will invoice you in the default currency (GBP, in the example). So the _desired prices are typically used to just display an indicative amount to the customer (in USD, in the example). Currency conversion rates are taken from a daily European Central Bank feed.
order See below for object detail.

Debitor data is returned when payment should be taken via Stripe. Stripe integration is described in detail within purchase.

debitor attributes:

Attribute Description
debitor_desc A human-readable description of the debitor.
debitor_integration_data Data you will need t
debitor_name The name of the debitor. For Stripe transactions this will be stripe.
debitor_type The type of the debitor. For Stripe transactions this will be stripe.

order attributes:

Attribute Description
event The event for this order.
item_number A unique sequential number for the order. The second order added to the trolley will have item_number 2. The item_number remains constant as orders are added or removed, so if item_number 1 is removed, the first order will be item_number 2.
performance The performance for this order.
price_band_code The code for a price band, for example “C/pool”. The price band code is generally made up of the code from the underlying supplier system, e.g. “C”, followed by a “/” separator then “pool” or “alloc”, indicating whether the price band is taken from the general pool of tickets or is from a ring-fenced allocation.
reserve_failure_comment A comment relating to why reserving this order failed. This field will appear when reserving the order failed and it lies in the unreserved_orders array.
seat_request_status The status of your tickets after they have been reserved. Possible values are not_requested (specific seats not requested), got_none (you requested A13 and A14 but we gave you A15 and A16), got_partial (you requested A13 and A14 but we gave you A14 and A15), got_all (you requested A13 and A14 and you got A13 and A14 - by far the most common response when requesting specific seats).
ticket_orders An array of ticket_order objects, one for each discount code. See below for detail.
ticket_type_code The unique identifier for the ticket type. For attractions this can refer to variations such as General Admission or Fast Track, and there is often only only. For seated events this normally refers to a part of house / seating area such as Grand Circle.
ticket_type_desc The description for the ticket type. This should be displayed to the customer
total_no_of_seats The number of tickets for this order.
total_sale_seatprice The total face value for this order.
total_sale_seatprice_in_desired The total face value for this order, converted to your desired_currency. This field will not be present for most partners.
total_sale_surcharge The total booking fee for this order.
total_sale_surcharge_in_desired The total booking fee for this order, converted to your desired_currency. This field will not be present for most partners.

ticket_order attributes:

Attribute Description
discount_code The discount code that applies to this ticket_order.
discount_desc The description for the discount code.
no_of_seats The number of tickets in this ticket_order.
sale_seatprice The face value per ticket in this ticket_order.
sale_seatprice_in_desired The face value per ticket in this ticket_order, converted to your desired_currency. This field will not be present for most partners.
sale_surcharge The booking fee per ticket in this ticket_order.
sale_surcharge_in_desired The booking fee per ticket in this ticket_order, converted to your desired_currency. This field will not be present for most partners.
seats For seated events, an array of reserved seats. See below for detail.
total_sale_seatprice The total face value of all tickets in this ticket_order.
total_sale_seatprice_in_desired The total face value of all tickets in this ticket_order, converted to your desired_currency. This field will not be present for most partners.
total_sale_surcharge The total booking fee of all tickets in this ticket_order.
total_sale_surcharge_in_desired The total booking fee of all tickets in this ticket_order, converted to your desired_currency. This field will not be present for most partners.

seats attributes:

Attribute Description
col_id The column identifier of the seat.
full_id The ID of the seat - comprised of the col_id and the row_id, sometimes with a separator between them.
is_restricted_view true if the seat is classified as having a restricted view.
row_id The row identifier of the seat.
seat_text A message about the seat that must be displayed to customers.
seat_text_code An identifier for the seat text (only unique within the current bundle_source_code). Not useful for most partners.

The outer object includes a currency_details object containing one currency object (indexed on the currency code) for every currency referenced in the JSON response. Each currency has the following attributes:

Attribute Description
currency_code ISO 4217 three letter code
currency_factor Multiply by this number to get values in the base unit (e.g. multiplying $47.11 by the currency_factor will give 4711 cents)
currency_number ISO 4217 numeric identifier
currency_places The number of decimal places to display (eg 45.5 usd should be displayed as 45.50)
currency_post_symbol A symbol to display at the end of the price
currency_pre_symbol A symbol to display in front of the price

Release

Definition

POST https://api.ticketswitch.com/f13/release.v1?transaction_uuid={trans_uuid}

This resource allows you to release previously-reserved tickets. It is important that your integration releases tickets as soon as it is clear that they will not be purchased, either because your customer explicitly removes them from a basket or similar, or because they implicitly imply that they want to continue browsing, for example by pressing back on your checkout page (when a user presses back on sites developed by Ingresso we release their reservation then request availability to ensure the user is also able to select the just-released tickets). This is necessary to ensure that all end users have the best possible access to tickets (including your other customers).

Request

Example request

curl https://api.ticketswitch.com/f13/release.v1 \
    -u "demo:demopass" \
    -d "transaction_uuid=f2158be3-d29e-11e6-8aab-0025903268dc" \
    --compressed \
    -X POST
from pyticketswitch import Client

client = Client('demo', 'demopass')
released = client.release_reservation('f2158be3-d29e-11e6-8aab-0025903268dc')
Parameter Description
transaction_uuid The unique identifier for a previous reserve.

Response

Example response

{
  "released_ok": true
}
True

This resource will return the same response when called multiple times.

Attribute Description
released_ok true if the release succeeded.

Purchase

Definition

POST https://api.ticketswitch.com/f13/purchase.v1

To purchase tickets you must first reserve them. You can then attempt to purchase the reserved tickets at any time within the reserve time (minutes_left_on_reserve). A successful result from purchase means that the order has been confirmed in the supplier ticketing system. Note that if you have attempted to purchase multiple events from a single trolley it is possible for a purchase to partially succeed, with some events unable to be purchased from the corresponding supplier ticketing system.

If a purchase fails due to incomplete or incorrect customer data then you can reattempt the purchase call with corrected data. If a purchase fails due to the reservation having timed out, then it is necessary to reserve tickets again. The output data is structured such that permanent failures are not reported as errors, but are reported as an actual result from a successful operation.

For purchases where a despatch method with a type of selfprint was selected, the URL returned should be presented to the customer.

Your payment option determines how you should call purchase. The two main options are:

On-credit purchasing

You take payment using a payment provider of your own choosing. When calling purchase you should just provide customer data, and the purchase call will return a success or failure.

Stripe

Stripe is a developer-friendly payment provider that is simple to integrate with. The Ingresso API provides a payment processing engine that gives you integration support for Stripe and other payment sources. You pass us a Stripe payment intent generated during your checkout, and we handle the rest. We support partners collecting payment via their own Stripe account or into Ingresso’s Stripe account.

In either case, you need integrate against Stripe.js and collect a Stripe token after your customer enters their payment details. The payment intent information is passed to Ingresso before making the purchase call.

If you want to collect payment via your own Stripe account you will need to get an agreement with us to sell tickets on credit, and we will invoice you for the ticket price less your commission. You will need to provide Ingresso your Stripe keys to allow us to process payment on your behalf.

If you wish to use Ingresso’s Stripe account we have some requirements to reduce fraud including implementing 3D Secure support and passing in the customer’s IP address, so please get in touch with us first. We however encourage partners to open their own Stripe account rather than use ours.

In the examples below we will describe how to purchase using the on-credit and Stripe options in more detail. We then describe how to handle generic redirects which are needed for other supported payment providers such as Global Collect. We recommend that all partners that wish to use Stripe also implement generic redirects - this is a small amount of additional development work that ensures you will be able to accept alternate payment methods both now and in future.

Notes on sending customer data

Confirmation Emails

After a successful purchase it is generally a good idea to send your customer a confirmation email reminding them of the items that they have purchased and including any relevant information such as directions or self print vouchers.

Ingresso can do this for you via the send_confirmation_email flag on the purchase call, or alternatively you can implement your own confirmation emails using the results of the status.v1 call.

Ingresso can style these emails to conform with your businesses branding. For more information drop us an email at affiliate@ingresso.co.uk.

Purchasing on credit

Request

Example request - purchasing on-credit

curl https://api.ticketswitch.com/f13/purchase.v1 \
    -u "demo:demopass" \
    -d "transaction_uuid=61cfd4eb-1f5b-11e7-b228-0025903268dc" \
    -d "first_name=Test" \
    -d "last_name=Tester" \
    -d "address_line_one=Metro Building" \
    -d "address_line_two=1 Butterwick" \
    -d "town=London" \
    -d "county=London" \
    -d "postcode=W6 8DL" \
    -d "country_code=uk" \
    -d "phone=0203 137 7420" \
    -d "user_can_use_customer_data=true" \
    -d "email_address=testing@gmail.com" \
    -d "send_confirmation_email=true" \
    -d "privacy_policy_version=2.2.1" \
    --compressed \
    -X POST
from pyticketswitch import Client
from pyticketswitch.customer import Customer


client = Client('demo', 'demopass')

customer = Customer(
    first_name='Test',
    last_name='Tester',
    address_lines=['Metro Building', '1 Butterwick'],
    town='London',
    county='London',
    post_code='W6 8DL',
    country_code='uk',
    phone='0203 137 7420',
    email='testing@gmail.com',
    user_can_use_customer_data=True,
)

status, callout, meta = client.make_purchase(
    '61cfd4eb-1f5b-11e7-b228-0025903268dc',
    customer,
    send_confirmation_email=True,
)

This section describes how to purchase on credit.

Parameter Description
address_line_one The first line of the customer’s address - required. Either pass your customer’s address or your head office address (see customer data note above).
address_line_two The second line of the customer’s address. Optional if address_line_one is provided.
agent_reference Partners can pass their own transaction reference to be stored in the Ingresso platform. Optional.
country_code The ISO 3166-1 alpha-2 country code of the customer’s address - required. The country code must have been present in the allowed_countries list from reserve.
county The county of region of the customer’s address. Optional.
email_address The customer’s email address. Required when needs_email_address was true from the reserve response. We recommend this is provided - see customer data note above.
first_name The customer’s first name - required. Used by venues as a security measure when admitting customers.
home_phone The customer’s home phone number. Optional if phone is provided.
initials The customer’s initials for their name. Optional.
last_name The customer’s last name - required. Used by venues as a security measure when admitting customers.
phone The customer’s phone number - required. Used by venues and Ingresso as a means to contact customers (see customer data note above). It is optional if you specify the work_phone and home_phone separately instead.
postcode The ZIP or postal code of the customer’s address. Optional.
suffix The suffix of the customer’s name, for example “Jr.” or “CPA” Optional.
send_confirmation_email When set to true Ingresso will send your customer a confirmation email with details of their purchase (including a link to a self print voucher when applicable). If you would prefer to send your own confirmation emails then do not specify this flag. Requries the email_address parameter to be provided.
supplier_can_use_customer_data Data protection question - set this to true if the customer has opted in to receiving marketing emails from the ticket supplier. Optional - it will default to false.
title The title of the customer’s name, for example “Mr.” or “Dr.” Optional.
town The city or town of the customer’s address. Optional.
transaction_uuid The unique reference for the reserved tickets, taken from the reserve response.
user_can_use_customer_data Data protection question - set this to true if the customer has opted in to receiving marketing emails from you. Most partners manage marketing opt-ins themselves so do not provide this. Ingresso will never send marketing communications to your customers based on this parameter. Optional - it will default to false.
work_phone The customer’s work phone number. Optional if phone is provided.
world_can_use_customer_data Data protection question - set this to true if the customer has opted in to receiving marketing emails communication from you and third-parties. Optional - it will default to false.
privacy_policy_version The version of your website privacy policy that the customer has agreed to. This is freeform text, not necessarily a number. Optional - it will default to blank.

All of the parameters used to request additional data for events can also be added.

Response

Example response - purchasing on-credit

{
  "currency_details": {
    "gbp": {
      "currency_code": "gbp",
      "currency_factor": 100,
      "currency_number": 826,
      "currency_places": 2,
      "currency_post_symbol": "",
      "currency_pre_symbol": "£"
    }
  },
  "customer": {
    "addr_line_one": "Metro Building",
    "addr_line_one_latin": "Metro Building",
    "addr_line_two": "1 Butterwick",
    "addr_line_two_latin": "1 Butterwick",
    "agent_ref": "",
    "country": "United Kingdom",
    "country_code": "uk",
    "country_latin": "United Kingdom",
    "county": "",
    "county_latin": "",
    "email_addr": "testing@gmail.com",
    "first_name": "Test",
    "first_name_latin": "Test",
    "home_phone": "0203 137 7420",
    "initials": "",
    "initials_latin": "",
    "last_name": "Tester",
    "last_name_latin": "Tester",
    "postcode": "W6 8DL",
    "postcode_latin": "W6 8DL",
    "privacy_policy_version": "2.2.1",
    "suffix": "",
    "suffix_latin": "",
    "supplier_can_use_customer_data": false,
    "title": "",
    "title_latin": "",
    "town": "London",
    "town_latin": "London",
    "user_can_use_customer_data": true,
    "work_phone": "0203 137 7420",
    "world_can_use_customer_data": false
  },
  "language_list": [
    "en-gb",
    "en",
    "en-us",
    "nl"
  ],
  "purchase_iso8601_date_and_time": "2017-04-12T08:38:35Z",
  "reserve_iso8601_date_and_time": "2017-04-12T08:38:20Z",
  "transaction_status": "purchased",
  "trolley_contents": {
    "bundle": [
      {
        "bundle_order_count": 1,
        "bundle_source_code": "ext_test0",
        "bundle_source_desc": "External Test Backend 0",
        "bundle_total_cost": 62.5,
        "bundle_total_seatprice": 51,
        "bundle_total_send_cost": 1.5,
        "bundle_total_surcharge": 10,
        "currency_code": "gbp",
        "order": [
          {
            "backend_purchase_reference": "PURCHASE-6710-1",
            "backend_cancellation_reference": "",
            "cancellation_comment" : "",
            "cancellation_status" : "possible",
            "event": {
              "city_code": "london-uk",
              "city_desc": "London",
              "classes": {
                "dance": "Ballet & Dance"
              },
              "country_code": "uk",
              "country_desc": "United Kingdom",
              "critic_review_percent": 100,
              "custom_filter": [],
              "event_desc": "Matthew Bourne's Nutcracker TEST",
              "event_id": "6IF",
              "event_path": "/6IF-matthew-bourne-s-nutcracker-test/",
              "event_status": "live",
              "event_type": "simple_ticket",
              "event_upsell_list": {
                "event_id": [
                  "6IE",
                  "MH0"
                ]
              },
              "event_uri_desc": "Matthew-Bourne%27s-Nutcracker-TEST",
              "geo_data": {
                "latitude": 51.52961137,
                "longitude": -0.10601562
              },
              "has_no_perfs": false,
              "is_seated": true,
              "max_running_time": 120,
              "min_running_time": 120,
              "need_departure_date": false,
              "need_duration": false,
              "need_performance": true,
              "postcode": "EC1R 4TN",
              "show_perf_time": true,
              "source_code": "ext_test0",
              "source_desc": "External Test Backend 0",
              "user_review_percent": 100,
              "venue_desc": "Sadler's Wells",
              "venue_uri_desc": "Sadler%27s-Wells"
            },
            "got_requested_seats": false,
            "gross_commission": {
              "amount_excluding_vat": 7.13,
              "amount_including_vat": 8.55,
              "commission_currency_code": "gbp"
            },
            "item_number": 1,
            "performance": {
              "date_desc": "Tue, 13th June 2017",
              "event_id": "6IF",
              "has_pool_seats": true,
              "is_ghost": false,
              "is_limited": false,
              "iso8601_date_and_time": "2017-06-13T19:30:00+01:00",
              "perf_id": "6IF-B1S",
              "perf_name": "Including back stage pass",
              "running_time": 120,
              "time_desc": "7.30 PM"
            },
            "price_band_code": "C/pool",
            "send_method": {
              "send_code": "COBO",
              "send_cost": 1.5,
              "send_desc": "Collect from the venue",
              "send_final_type": "collect",
              "send_type": "collect"
            },
            "supported_barcode_types": [
              "qr_code"
            ],
            "ticket_orders": {
              "ticket_order": [
                {
                  "discount_code": "ADULT",
                  "discount_desc": "Adult",
                  "no_of_seats": 1,
                  "sale_seatprice": 25,
                  "sale_surcharge": 4,
                  "seats": [
                    {
                      "col_id": "386",
                      "full_id": "NM386",
                      "is_restricted_view": false,
                      "row_id": "NM"
                    }
                  ],
                  "total_sale_seatprice": 25,
                  "total_sale_surcharge": 4
                },
                {
                  "discount_code": "CHILD",
                  "discount_desc": "Child rate",
                  "no_of_seats": 2,
                  "sale_seatprice": 13,
                  "sale_surcharge": 3,
                  "seats": [
                    {
                      "col_id": "383",
                      "full_id": "NM383",
                      "is_restricted_view": false,
                      "row_id": "NM"
                    },
                    {
                      "col_id": "380",
                      "full_id": "NM380",
                      "is_restricted_view": false,
                      "row_id": "NM"
                    }
                  ],
                  "total_sale_seatprice": 26,
                  "total_sale_surcharge": 6
                }
              ]
            },
            "ticket_type_code": "CIRCLE",
            "ticket_type_desc": "Upper circle",
            "total_no_of_seats": 3,
            "total_sale_seatprice": 51,
            "total_sale_surcharge": 10,
            "user_commission": {
              "amount_excluding_vat": 3.21,
              "amount_including_vat": 3.85,
              "commission_currency_code": "gbp"
            }
          }
        ],
        "purchase_result": {
          "is_semi_credit": false,
          "success": true
        }
      }
    ],
    "purchase_result": {
      "is_partial": false,
      "success": true
    },
    "transaction_id": "T000-0000-8RGW-3619",
    "transaction_uuid": "61cfd4eb-1f5b-11e7-b228-0025903268dc",
    "trolley_bundle_count": 1,
    "trolley_order_count": 1
  }
}
from pyticketswitch.send_method import SendMethod
from pyticketswitch.purchase_result import PurchaseResult
from pyticketswitch.seat import Seat
from pyticketswitch.event import Event
from pyticketswitch.status import Status
from pyticketswitch.customer import Customer
from pyticketswitch.bundle import Bundle
from pyticketswitch.performance import Performance
from pyticketswitch.order import TicketOrder
from pyticketswitch.trolley import Trolley
from pyticketswitch.order import Order

# An on credit purchase should always return a status object and will never
# return a callout.
Status(
    status='purchased',
    reserved_at=datetime.datetime(2017, 5, 3, 15, 1, 45, tzinfo=tzutc()),
    purchased_at=datetime.datetime(2017, 5, 3, 15, 14, 5, tzinfo=tzutc()),
    trolley=Trolley(
        transaction_uuid='6d080a78-3011-11e7-b228-0025903268dc',
        transaction_id='T000-0000-8ZVV-2E78',
        bundles=[
            Bundle(
                source_code='ext_test1',
                orders=[
                    Order(
                        item=1,
                        cancellation_comment='',
                        cancellation_status='possible',
                        event=Event(
                            id='7AB',
                            status='live',
                            description='The Unremarkable Incident of the Cat at Lunchtime',
                            source='External Test Backend 1',
                            source_code='ext_test1',
                            event_type='simple_ticket',
                            venue='Lyric Apollo',
                            classes={
                                'theatre': 'Theatre'
                            },
                            postcode='W6 7ES',
                            city='London',
                            city_code='london-uk',
                            country='United Kingdom',
                            country_code='uk',
                            latitude=51.49306,
                            longitude=-0.22639,
                            max_running_time=90,
                            min_running_time=90,
                            show_performance_time=True,
                            has_performances=True,
                            is_seated=True,
                            needs_departure_date=False,
                            needs_duration=False,
                            needs_performance=False,
                        ),
                        performance=Performance(
                            id='7AB-5',
                            event_id='7AB',
                            date_time=datetime.datetime(2019, 1, 1, 15, 30, tzinfo=tzutc()) ,
                            date_description='Tue, 1st January 2019',
                            time_description='3.30 PM',
                            has_pool_seats=True,
                            is_limited=False,
                            is_ghost=False,
                            running_time=90,
                        ),
                        price_band_code='A/pool',
                        ticket_type_code='STALLS',
                        ticket_type_description='Stalls',
                        ticket_orders=[
                            TicketOrder(
                                code='NORMAL',
                                seats=[
                                    Seat(
                                        id='A1',
                                        column='1',
                                        row='A',
                                        separator='',
                                        is_restricted=True,
                                        seat_text='Restricted View',
                                    ),
                                    Seat(
                                        id='A2',
                                        column='2',
                                        row='A',
                                        separator='',
                                        is_restricted=True,
                                        seat_text='Restricted View',
                                    )
                                ],
                                description='Regular Ticket',
                                number_of_seats=2,
                                seatprice=50.0,
                                surcharge=5.0,
                                total_seatprice=100.0,
                                total_surcharge=10.0,
                            )
                        ],
                        number_of_seats=2,
                        total_seatprice=100.0,
                        total_surcharge=10.0,
                        seat_request_status='got_all',
                        requested_seat_ids=[
                            'A1',
                            'A2'
                        ],
                        backend_purchase_reference='PURCHASE-DA6E-0',
                        backend_cancellation_reference='',
                        send_method=SendMethod(
                            code='VOUCH',
                            cost=0.0,
                            description='Printable eTicket',
                            type='selfprint',
                            can_generate_self_print=False,
                            self_print_voucher_url='https://api.ticketswitch.com/tickets/web_self_print.buy/demo?crypto_block=M_--R-aJRIR74rjx8gM2szdo9BEJZ8oV6wfGukxyZGDA2_DU2K3w-Y8L_3LWvIgKO_QxwMN8WmasaUuL_WpzKS-q2roXIWxXqjTxyDYZdge-wjDI0RZ8NpBAS0--Y',
                        ),
                    )
                ],
                description='External Test Backend 1',
                total_seatprice=100.0,
                total_surcharge=10.0,
                total_send_cost=0.0,
                total=110.0,
                currency_code='gbp',
            )
        ],
        purchase_result=PurchaseResult(
            success=True,
        ),
    ),
    languages=[
        'en'
    ],
    customer=Customer(
        first_name='Test',
        first_name_latin='Test',
        last_name='Tester',
        last_name_latin='Tester',
        address_lines=[
            'Metro Building',
            '1 Butterwick'
        ],
        address_lines_latin=[
            'Metro Building',
            '1 Butterwick'
        ],
        title='',
        title_latin='',
        initials='',
        initials_latin='',
        suffix='',
        suffix_latin='',
        country_code='uk',
        post_code='W6 8DL',
        post_code_latin='W6 8DL',
        town='London',
        town_latin='London',
        county='London',
        county_latin='London',
        country='United Kingdom',
        country_latin='United Kingdom',
        email='',
        home_phone='0203 137 7420',
        work_phone='0203 137 7420',
        agent_reference='',
        supplier_can_use_data=False,
        user_can_use_data=True,
        world_can_use_data=False,
    ),
)
Attribute Description
customer See below for object detail.
language_list Not useful for most partners, can be ignored.
purchase_iso8601_date_and_time The purchase time in ISO 8601 format.
reserve_iso8601_date_and_time The reserve time in ISO 8601 format.
transaction_status purchased, failed or attempting (will only be seen if the customer is being redirected to a payment page - most partners will not see this).
trolley_contents See below for object detail.

customer attributes:

Attribute Description
addr_line_one The first line of the customer’s address.
addr_line_one_latin The first line of the customer’s address, converted to Latin characters (this should allow a European latin alphabet language speaker to read an address containing only Japanese or Chinese characters, for example).
addr_line_two The second line of the customer’s address, if provided.
addr_line_two_latin The second line of the customer’s address, if provided, converted to Latin characters.
agent_ref A partner transaction reference, if this was passed in as a parameter.
country The country from the customer’s address.
country_code The ISO 3166-1 alpha-2 country code of the customer’s address.
country_latin The country, converted to Latin characters.
county The county from the customer’s address, if provided.
county_latin The county, converted to Latin characters.
dp_supplier Has the customer opted in to receiving marketing emails from the ticket supplier.
dp_user Has the customer opted in to receiving marketing emails from you.
dp_world Has the customer opted in to receiving marketing emails communication from you and third-parties.
email_addr The customer’s email address, if provided.
first_name The customer’s first name.
first_name_latin The customer’s first name, converted to Latin characters.
home_phone The customer’s home phone number.
initials The initials of the customer’s name, if provided.
initials_latin The customer’s initials, converted to Latin characters.
last_name The customer’s surname.
last_name_latin The customer’s surname, converted to Latin characters.
postcode The customer’s postcode, if provided.
postcode_latin The customer’s postcode, converted to Latin characters.
suffix The suffix of the customer’s name, if provided.
suffix_latin The customer’s suffix, converted to Latin characters.
title The title of the customer’s name, if provided.
title_latin The customer’s title, converted to Latin characters.
town The customer’s town or city, if provided.
town_latin The customer’s town, converted to Latin characters.
work_phone The customer’s work phone number.

trolley_contents attributes:

Attribute Description
bundle An array of bundles. A bundle is a group of orders purchased from a single supplier ticketing system. See below for object detail.
purchase_result.is_partial true if you attempted to purchase items from more than one supplier ticketing system (therefore you attempted to purchase multiple bundles), but only some of the purchases were successful.
purchase_result.success true if the purchase succeeded if at least one of the bundles succeeded.
transaction_id The primary Ingresso transaction reference.
transaction_uuid The secondary Ingresso transaction reference.
trolley_bundle_count The number of bundles in the trolley (a bundle is a group of orders purchased from a single supplier ticketing system).
trolley_order_count The number of orders in the trolley (an order is tickets for a single event).

bundle attributes:

Attribute Description
bundle_order_count The number of orders (i.e. events) in this bundle.
bundle_source_code The code Ingresso use to identify the supplier ticketing system.
bundle_source_desc The description of the supplier ticketing system.
bundle_total_cost bundle_total_seatprice + bundle_total_surcharge + bundle_total_send_cost.
bundle_total_cost_in_desired bundle_total_seatprice_in_desired + bundle_total_surcharge_in_desired + bundle_total_send_cost_in_desired.
bundle_total_seatprice The total face value.
bundle_total_seatprice_in_desired The total face value in your desired currency. This field won’t be present unless you have requested a desired currency.
bundle_total_send_cost The total cost for despatching tickets.
bundle_total_send_cost_in_desired The total despatch cost in your desired currency.
bundle_total_surcharge The total booking fee.
bundle_total_surcharge_in_desired The total booking fee in your desired currency.
currency The currency of the costs.
desired_currency Your desired currency, if this has been requested.
order See below for object detail.
purchase_result.is_semi_credit Legacy - can be ignored.
purchase_result.success true if the purchase succeeded for this bundle.

order attributes:

Attribute Description
backend_purchase_reference The purchase reference from the supplier ticketing system. This reference should be included on customer confirmation emails and self-print vouchers as this is the only reference that the venue will recognise.
backend_cancellation_reference The cancellation reference from the supplier ticketing system. This will usually be empty until a cancellation has been attempted.
cancellation_comment A comment from the cancellation attempt.
cancellation_status If this is not_permitted then it is not possible to cancel this order, if it is possible then it is possible to cancel this order, see cancellations.
event The event object, with the same format as for the events endpoint.
gross_commission The total commission available to both Ingresso and the partner. This will only be visible for partners on margin share agreements or where Ingresso take a fixed fee. If you believe you should have gross_commission visible please contact us
gross_commission.amount_excluding_vat The total commission amount excluding sales tax.
gross_commission.amount_including_vat The total commission amount including sales tax.
gross_commission.commission_currency The commission currency (note that this can be different to the currency seen by the customer).
item_number Each order item within a transaction has an item_number, starting at 1.
performance The performance object, with the same format as for the performances endpoint.
price_band_code The code for a price band, for example “C/pool”. The price band code is generally made up of the code from the underlying supplier system, e.g. “C”, followed by a “/” separator then “pool” or “alloc”, indicating whether the price band is taken from the general pool of tickets or is from a ring-fenced allocation.
seat_request_status The status of your tickets after they have been reserved. Possible values are not_requested (specific seats not requested), got_none (you requested A13 and A14 but we gave you A15 and A16), got_partial (you requested A13 and A14 but we gave you A14 and A15), got_all (you requested A13 and A14 and you got A13 and A14 - by far the most common response when requesting specific seats).
send_method See below for object detail.
supported_barcode_types An array of strings. See below for possible values
ticket_orders An array of ticket_order objects, one for each discount code. See below for detail.
ticket_type_code The unique identifier for the ticket type. For attractions this can refer to variations such as General Admission or Fast Track, and there is often only only. For seated events this normally refers to a part of house / seating area such as Grand Circle.
ticket_type_desc The description for the ticket type. This should be displayed to the customer
total_no_of_seats The number of tickets for this order.
total_sale_seatprice The total face value for this order.
total_sale_seatprice_in_desired The total face value for this order, converted to your desired_currency. This field will not be present for most partners.
total_sale_surcharge The total booking fee for this order.
total_sale_surcharge_in_desired The total booking fee for this order, converted to your desired_currency. This field will not be present for most partners.
user_commission The commission you earn from this transaction.
user_commission.amount_excluding_vat Your commission excluding sales tax.
user_commission.amount_excluding_vat Your commission excluding sales tax.
user_commission.amount_including_vat Your commission including sales tax.
user_commission.commission_currency The commission currency (note that this can be different to the currency seen by the customer).

send_method attributes:

Attribute Description
can_generate_self_print true if you are allowed up to produce your own self print vouchers (eTickets), false if you have to use the voucher URL below.
has_html_page true if an HTML voucher is returned.
self_print_voucher_url The voucher / eTicket URL. This should be displayed to your customer.
send_code The code for this send method.
send_cost The despatch cost for the chosen send method.
send_cost_in_desired The despatch cost for the chosen send method, converted to your desired currency if you have one (in most cases this won’t be present).
send_desc The description for this send method.
send_final_comment . Will not always be present.
send_final_type The classification of send method: one of selfprint, collect or post. The final_type should be the same as the type.
send_type The classification of send method: one of selfprint, collect or post.

supported_barcode_types values:

An array of strings with the following possible values:

ticket_order attributes:

Attribute Description
discount_code The discount code that applies to this ticket_order.
discount_desc The description for the discount code.
no_of_seats The number of tickets in this ticket_order.
sale_seatprice The face value per ticket in this ticket_order.
sale_seatprice_in_desired The face value per ticket in this ticket_order, converted to your desired_currency. This field will not be present for most partners.
sale_surcharge The booking fee per ticket in this ticket_order.
sale_surcharge_in_desired The booking fee per ticket in this ticket_order, converted to your desired_currency. This field will not be present for most partners.
seats For seated events, an array of reserved seats. See below for detail.
total_sale_seatprice The total face value of all tickets in this ticket_order.
total_sale_seatprice_in_desired The total face value of all tickets in this ticket_order, converted to your desired_currency. This field will not be present for most partners.
total_sale_surcharge The total booking fee of all tickets in this ticket_order.
total_sale_surcharge_in_desired The total booking fee of all tickets in this ticket_order, converted to your desired_currency. This field will not be present for most partners.

seats attributes:

Attribute Description
col_id The column identifier of the seat.
full_id The ID of the seat - comprised of the col_id and the row_id, sometimes with a separator between them.
is_restricted_view true if the seat is classified as having a restricted view.
row_id The row identifier of the seat.
seat_text A message about the seat that must be displayed to customers.
seat_text_code An identifier for the seat text (only unique within the current bundle_source_code). Not useful for most partners.
barcode The barcode data for the ticket if returned by the supplier system.

Purchasing with Stripe

Ingresso have an integration with Stripe for credit card processing, and can accept payment on your behalf from your customers. Ingresso Payments has a completed PCI-DSS SAQ-D and attestation of compliance as a payment service provider and our card payments solution uses Stripe to ensure no cardholder data goes through our systems.

There are two ways that you can integrate with Ingresso using Stripe. The Ingresso white label is fully integrated on the front- and back-end with Stripe and is EU PSD2-compliant with support for Strong Customer Authentication, Apple Pay and Google Pay and mobile-ready. This is our recommended approach to integrating using Ingresso’s payment services as this integration is well-tested, has thorough error handling for when payments or bookings fail and can be styled to match your branding while also keeping the booking flow and post-checkout flow on your own platform - you can simply redirect the customer to the Ingresso checkout page, and have them redirected back to you once payment has been taken.

The other way is to do the work of integrating with Stripe on your own site and sending tokenised payment information to Ingresso with the purchase request, and implementing all of the error handling and compliance support on your own platform - this gives you the greatest level of control over the user experience, but is a somewhat complex undertaking, which is why Ingresso recommends leveraging the white label solution for most partners.

Purchasing with Stripe requires your API user to be set up to use the Ingresso Payments service, which will require contacting us. If you are interested in testing this functionality, the demo-stripe user has been created which is already set up this way. The password is the same as for the demo user. After creating a reservation with this user, you can proceed to test purchasing with Stripe, as outlined below.

Purchasing with a Stripe payment intent

In order to purchase with Stripe you need the following steps:

  1. Create a Stripe payment intent and collect payment information (further detail below).
  2. Save the Stripe payment intent in our payment processing engine, which will return a unique token as a reference
  3. Call purchase.v1 passing in the payment engine reference from step 2.

Note that you need to retrieve and pass in one payment engine token for each bundle that you reserve. If you only support the purchase of one item at a time, or if you don’t use the Ingresso API to help manage basketing then you can ignore this.

Generating a Stripe payment intent

Stripe allows you to create a payment intent at the start of a customer checkout and use this to collect payment information on your behalf. The payment information can either be collected on your own checkout page in a PCI-compliant manner (“Elements”), with a mobile-friendly form (“Checkout”), or via their mobile SDKs. See Stripe’s Quickstart guide.

You will need to provide Stripe with the appropriate publishable key - this is returned by Ingresso in the reserve call as bundle.debitor.debitor_integration_data.stripe.publishable_key.

Using Stripe payment intents ensures that you are able to meet the European Strong Customer Authentication (SCA) regulation when processing payments.

When creating a Stripe payment intent you’ll need to set its capture_method to 'manual'. This will allow Stripe’s Elements or SDKs used within your checkout page to handle any customer verification needed for 3D Secure 2 while still allowing Ingresso to process payments on your behalf. See Stripe’s ‘Creating Payment Intents’ docs for more info on this.

Saving the Stripe payment intent in the Ingresso Payments system

Example saving payment details

curl https://payments.ingresso.co.uk/api/save-details \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer key_XYZ789123" \
    -X POST \
    -d @- << EOF
{
    "stripe_payment_intent": "pi_ABCD1234",
    "stripe_meta_email_address": "customer@example.com",
    "stripe_meta_event_ids": "6IF",
    "stripe_meta_send_methods": "collect",
    "stripe_meta_days_to_performance": 37,
    "stripe_meta_user_id": "demo",
    "stripe_meta_ip_address": "101.102.103.104"
}
EOF
# We suggest Javascript integration on the front end, but you can use
# a HTTP requests library if you'd prefer.
const integration_data = {
    cider_api_endpoint: "https://payments.ingresso.co.uk/api",
    cider_api_token: "key_XYZ789123",
};

// get Stripe token
let stripePaymentIntent = "pi_ABCD1234";

const http = new XMLHttpRequest();
http.open('POST', integration_data.cider_api_endpoint + '/save-details', true);
http.setRequestHeader('Content-type', 'application/json');
http.setRequestHeader('Authorization', 'Bearer ' + integration_data.cider_api_key);
http.onload = () => {
    if (http.status === 200) {
        // get token from response
    } else {
        // handle error
    }
};
http.onerror = () => console.log("Unable to connect");
http.ontimeout = () => console.log("Connection timed out.");
http.send(JSON.stringify({ stripe_payment_intent: stripePaymentIntent }));

Example response

{"token": "cider_XYZ789123"}

Once you have a Stripe payment intent, you must save it in Ingresso’s payment processing Engine (called Cider). The API endpoint you can use is also found in the reserve call integration data, as bundle.debitor.debitor_integration_data.cider_api_endpoint. You will need to use a unique key per reservation, found at debitor_integration_data.cider_api_token.

The API endpoint will look something like https://payments.ingresso.co.uk/api and you can save the stripe payment intent generated above by making a HTTP POST request to this endpoint + /save-details, and authenticating with the key provided in the integration data.

In addition to saving Stripe payment intents, you can also save metadata about the purchase to this endpoint, which will be saved in Stripe against the purchase record. This is very important for anti-fraud rules when using the Ingresso Stripe account, and may be useful for your own account too.

You must pass in the actual customer’s remote_ip if you are taking payment via Ingresso’s Stripe account - we use this for fraud checks. It is also useful to pass in the remote_site so we know which website the customer purchased on.

One primary advantage of saving the details in this way is that it will not appear in Ingresso’s logs or database, and is only used as metadata in Stripe, so it reduces the spread of personally identifiable information. Please note that the call must include a valid Authorization header with the key included in the reservation response debitor integration data, and should be well-formed JSON, as per the examples.

Making the purchase call

Creating a Stripe payment intent is the first half of the payment process - further server-side code is required to complete the second half. You don’t need to worry about this as Ingresso’s payment processor takes care of it. Once you have saved the Stripe payment intent and retrieved the cider token, we will handle the following steps:

Purchase request

Example purchase request - Stripe

curl https://demo.ticketswitch.com/f13/purchase.v1 \
    -u "demo-stripe:demopass" \
    -d "transaction_uuid=2e740db5-1b65-11e7-9e97-002590326932" \
    -d "first_name=Test" \
    -d "last_name=Tester" \
    -d "address_line_one=Metro Building" \
    -d "address_line_two=1 Butterwick" \
    -d "town=London" \
    -d "county=London" \
    -d "postcode=W6 8DL" \
    -d "country_code=uk" \
    -d "phone=0203 137 7420" \
    -d "email_address=tester@gmail.com" \
    -d "ext_test0_callback/cider_token=cider_XYZ789123" \
    -d "send_confirmation_email=yes" \
    -d "remote_ip=101.102.103.104" \
    -d "remote_site=www.myticketshop.com" \
    --compressed \
    -X POST
from pyticketswitch import Client
from pyticketswitch.customer import Customer
from pyticketswitch.payment_methods import CiderDetails


client = Client('demo-stripe', 'demopass')

customer = Customer(
    first_name='Test',
    last_name='Tester',
    address_lines=['Metro Building', '1 Butterwick'],
    town='London',
    county='London',
    post_code='W6 8DL',
    country_code='uk',
    phone='0203 137 7420',
    email='testing@gmail.com',
    user_can_use_customer_data=True,
)

cider_details = CiderDetails(
    {'cider_token': 'cider_XYZ789123'},
    ['ext_test0'],
)

status, callout, meta = client.make_purchase(
    '7150d25f-301b-11e7-bede-0025903268a0',
    customer,
    payment_method=cider_details,
    send_confirmation_email=True,
)

To complete a test Stripe purchase:

  1. Call reserve
  2. Create a Stripe payment intent
  3. Enter and handle test card details with the Stripe Elements example form using the Stripe payment intent’s client_secret.
  4. Save the Stripe payment intent ID in the Ingresso Payments processing service (Cider)
  5. Call purchase, replacing the transaction_uuid and ext_test0_callback/cider_token with the values from the 4 steps above.

All of the parameters mentioned above in the purchasing on credit section are used. In addition the following parameter should be specified:

Parameter Description
remote_ip The end customer’s IP address.
remote_site The website the end customer is purchasing from, not including https:// or http://.
X_callback/cider_token The single-use token retrieved from Cider after saving the stripe payment intent being used. You should replace X with the source_code returned by reserve. So for source_code=ext_test0 the parameter name used is ext_test0_callback/cider_token. If you support basketing and your customer is attempting to purchase items across multiple bundles, you should provide the same Cider token for each bundle (each bundle has a unique source_code).

Purchase response

Example purchase response - Stripe

{
  "currency_details": {
    "gbp": {
      "currency_code": "gbp",
      "currency_factor": 100,
      "currency_number": 826,
      "currency_places": 2,
      "currency_post_symbol": "",
      "currency_pre_symbol": "£"
    }
  },
  "customer": {
    "addr_line_one": "Metro Building",
    "addr_line_one_latin": "Metro Building",
    "addr_line_two": "1 Butterwick",
    "addr_line_two_latin": "1 Butterwick",
    "agent_ref": "",
    "country": "United Kingdom",
    "country_code": "uk",
    "country_latin": "United Kingdom",
    "county": "",
    "county_latin": "",
    "dp_supplier": false,
    "dp_user": false,
    "dp_world": false,
    "email_addr": "tester@gmail.com",
    "first_name": "Test",
    "first_name_latin": "Test",
    "home_phone": "0203 137 7420",
    "initials": "",
    "initials_latin": "",
    "last_name": "Tester",
    "last_name_latin": "Tester",
    "postcode": "W6 8DL",
    "postcode_latin": "W6 8DL",
    "suffix": "",
    "suffix_latin": "",
    "title": "",
    "title_latin": "",
    "town": "London",
    "town_latin": "London",
    "work_phone": "0203 137 7420"
  },
  "language_list": "en-gb,en,en-us,nl",
  "purchase_iso8601_date_and_time": "2017-03-03T15:58:26Z",
  "reserve_iso8601_date_and_time": "2017-03-03T15:58:01Z",
  "transaction_status": "purchased",
  "trolley_contents": {
    "bundle": [
      {
        "bundle_order_count": 1,
        "bundle_source_code": "ext_test0",
        "bundle_source_desc": "External Test Backend 0",
        "bundle_total_cost": 62.5,
        "bundle_total_seatprice": 51,
        "bundle_total_send_cost": 1.5,
        "bundle_total_surcharge": 10,
        "currency_code": "gbp",
        "order": [
          {
            "backend_purchase_reference": "PURCHASE-17BB2-1",
            "cancellation_comment" : "",
            "cancellation_status" : "possible",
            "event": {
              "city_code": "london-uk",
              "city_desc": "London",
              "classes": {
                "dance": "Ballet & Dance"
              },
              "country_code": "uk",
              "country_desc": "United Kingdom",
              "critic_review_percent": 100,
              "custom_filter": [],
              "event_desc": "Matthew Bourne's Nutcracker TEST",
              "event_id": "6IF",
              "event_path": "/6IF-matthew-bourne-s-nutcracker-test/",
              "event_status": "live",
              "event_type": "simple_ticket",
              "event_upsell_list": {
                "event_id": [
                  "6IE",
                  "MH0"
                ]
              },
              "event_uri_desc": "Matthew-Bourne%27s-Nutcracker-TEST",
              "geo_data": {
                "latitude": 51.52961137,
                "longitude": -0.10601562
              },
              "has_no_perfs": false,
              "is_seated": true,
              "max_running_time": 120,
              "min_running_time": 120,
              "need_departure_date": false,
              "need_duration": false,
              "need_performance": true,
              "postcode": "EC1R 4TN",
              "show_perf_time": true,
              "source_code": "ext_test0",
              "source_desc": "External Test Backend 0",
              "user_review_percent": 100,
              "venue_desc": "Sadler's Wells",
              "venue_uri_desc": "Sadler%27s-Wells"
            },
            "got_requested_seats": false,
            "gross_commission": {
              "amount_excluding_vat": 7.13,
              "amount_including_vat": 8.55,
              "commission_currency_code": "gbp"
            },
            "item_number": 1,
            "performance": {
              "date_desc": "Tue, 13th June 2017",
              "event_id": "6IF",
              "has_pool_seats": true,
              "is_ghost": false,
              "is_limited": false,
              "iso8601_date_and_time": "2017-06-13T19:30:00+01:00",
              "perf_id": "6IF-B1S",
              "perf_name": "Including back stage pass",
              "running_time": 120,
              "time_desc": "7.30 PM"
            },
            "price_band_code": "C/pool",
            "send_method": {
              "send_code": "COBO",
              "send_cost": 1.5,
              "send_desc": "Collect from the venue",
              "send_final_type": "collect",
              "send_type": "collect"
            },
            "ticket_orders": {
              "ticket_order": [
                {
                  "discount_code": "ADULT",
                  "discount_desc": "Adult",
                  "no_of_seats": 1,
                  "sale_seatprice": 25,
                  "sale_surcharge": 4,
                  "seats": [
                    {
                      "col_id": "419",
                      "full_id": "OR419",
                      "is_restricted_view": false,
                      "row_id": "OR"
                    }
                  ],
                  "total_sale_seatprice": 25,
                  "total_sale_surcharge": 4
                },
                {
                  "discount_code": "CHILD",
                  "discount_desc": "Child rate",
                  "no_of_seats": 2,
                  "sale_seatprice": 13,
                  "sale_surcharge": 3,
                  "seats": [
                    {
                      "col_id": "416",
                      "full_id": "OR416",
                      "is_restricted_view": false,
                      "row_id": "OR"
                    },
                    {
                      "col_id": "413",
                      "full_id": "OR413",
                      "is_restricted_view": false,
                      "row_id": "OR"
                    }
                  ],
                  "total_sale_seatprice": 26,
                  "total_sale_surcharge": 6
                }
              ]
            },
            "ticket_type_code": "CIRCLE",
            "ticket_type_desc": "Upper circle",
            "total_no_of_seats": 3,
            "total_sale_seatprice": 51,
            "total_sale_surcharge": 10,
            "user_commission": {
              "amount_excluding_vat": 0,
              "amount_including_vat": 0,
              "commission_currency_code": "gbp"
            }
          }
        ],
        "purchase_result": {
          "is_semi_credit": false,
          "success": true
        }
      }
    ],
    "purchase_result": {
      "is_partial": false,
      "success": true
    },
    "transaction_id": "T000-0000-8N66-K30B",
    "transaction_uuid": "2dac0d00-002a-11e7-975c-002590326962",
    "trolley_bundle_count": 1,
    "trolley_order_count": 1
  }
}
from pyticketswitch.customer import Customer
from pyticketswitch.trolley import Trolley
from pyticketswitch.debitor import Debitor
from pyticketswitch.status import Status
from pyticketswitch.seat import Seat
from pyticketswitch.performance import Performance
from pyticketswitch.order import TicketOrder
from pyticketswitch.purchase_result import PurchaseResult
from pyticketswitch.event import Event
from pyticketswitch.send_method import SendMethod
from pyticketswitch.order import Order
from pyticketswitch.bundle import Bundle

# stripe purchases should always return a status object, and no callout.
Status(
    status='purchased',
    reserved_at=datetime.datetime(2017, 5, 3, 16, 13, 28, tzinfo=tzutc()),
    purchased_at=datetime.datetime(2017, 5, 3, 16, 14, 19, tzinfo=tzutc()),
    trolley=Trolley(
        transaction_uuid='7150d25f-301b-11e7-bede-0025903268a0',
        transaction_id='T000-0000-8ZW5-68A8',
        bundles=[
            Bundle(
                source_code='ext_test0',
                orders=[
                    Order(
                        item=1,
                        cancellation_comment='',
                        cancellation_status='possible',
                        event=Event(
                            id='6IF',
                            status='live',
                            description="Matthew Bourne's Nutcracker TEST",
                            source='External Test Backend 0',
                            source_code='ext_test0',
                            event_type='simple_ticket',
                            venue="Sadler's Wells",
                            classes={
                                'dance': 'Ballet & Dance'
                            },
                            filters=[

                            ],
                            postcode='EC1R 4TN',
                            city='London',
                            city_code='london-uk',
                            country='United Kingdom',
                            country_code='uk',
                            latitude=51.52961137,
                            longitude=-0.10601562,
                            max_running_time=120,
                            min_running_time=120,
                            show_performance_time=True,
                            has_performances=True,
                            is_seated=True,
                            needs_departure_date=False,
                            needs_duration=False,
                            needs_performance=False,
                            upsell_list=[
                                '6IE',
                                'MH0'
                            ],
                            critic_review_percent=100,
                        ),
                        performance=Performance(
                            id='6IF-B0O',
                            event_id='6IF',
                            date_time=datetime.datetime(2017, 5, 4, 19, 30, tzinfo=tzoffset(None, 3600)),
                            date_description='Thu, 4th May 2017',
                            time_description='7.30 PM',
                            has_pool_seats=True,
                            is_limited=False,
                            is_ghost=False,
                            running_time=120,
                        ),
                        price_band_code='A/pool',
                        ticket_type_code='STALLS',
                        ticket_type_description='Stalls',
                        ticket_orders=[
                            TicketOrder(
                                code='',
                                seats=[
                                    Seat(
                                        id='JM189',
                                        column='189',
                                        row='JM',
                                        separator='',
                                        is_restricted=False,
                                    ),
                                    Seat(
                                        id='JM190',
                                        column='190',
                                        row='JM',
                                        separator='',
                                        is_restricted=False,
                                    )
                                ],
                                description='',
                                number_of_seats=2,
                                seatprice=21.0,
                                surcharge=3.0,
                                total_seatprice=42.0,
                                total_surcharge=6.0,
                            )
                        ],
                        number_of_seats=2,
                        total_seatprice=42.0,
                        total_surcharge=6.0,
                        seat_request_status='not_requested',
                        requested_seat_ids=[

                        ],
                        backend_purchase_reference='PURCHASE-11F22-1',
                        send_method=SendMethod(
                            code='COBO',
                            cost=1.5,
                            description='Collect from the venue',
                            type='collect',
                        ),
                    )
                ],
                description='External Test Backend 0',
                total_seatprice=42.0,
                total_surcharge=6.0,
                total_send_cost=1.5,
                total=49.5,
                currency_code='gbp',
                debitor=Debitor(
                    type='cider',
                    name='cider',
                    description='Cider',
                    integration_data={
                        'cider_api_token': 'key_XYZ789123',
                        'cider_api_endpoint': 'https://payments.ingresso.co.uk/api',
                        'cider_js': 'https://payments.ingresso.co.uk/static/js/cider/cider.js',
                        'merchant_group_country_code': 'gb',
                        'stripe': {
                            'publishable_key': 'pk_test_b7N9DOwbo4B9t6EqCf9jFzfa',
                            'payment_sources_enabled': true,
                            'required': true,
                        },
                    },
                ),
            )
        ],
        discarded_orders=[

        ],
        purchase_result=PurchaseResult(
            success=True,
        ),
    ),
    languages=[
        'en'
    ],
    customer=Customer(
        first_name='Test',
        first_name_latin='Test',
        last_name='Tester',
        last_name_latin='Tester',
        address_lines=[
            'Metro Building',
            '1 Butterwick'
        ],
        address_lines_latin=[
            'Metro Building',
            '1 Butterwick'
        ],
        title='',
        title_latin='',
        initials='',
        initials_latin='',
        suffix='',
        suffix_latin='',
        country_code='uk',
        post_code='W6 8DL',
        post_code_latin='W6 8DL',
        town='London',
        town_latin='London',
        county='London',
        county_latin='London',
        country='United Kingdom',
        country_latin='United Kingdom',
        email='testing@gmail.com',
        home_phone='0203 137 7420',
        work_phone='0203 137 7420',
        agent_reference='',
    ),
)

The response is identical to the purchase response described in purchasing on credit.

Using the Ingresso white label

To use the Ingresso white label solution only for the checkout functionality, you will need at a minimum the transaction_uuid from the reserve step. However, for optimal customer experience it is also highly recommended that you provide a trolley_token that was used to create the reservation as well.

For your live integration you will need to contact us to get a white label created for you that has your branding and configuration created, but for the purposes of integration you can test against the white label at https://demo-stripe.ticketswitch.com/ using the demo-stripe user as above.

Create a 302 redirect to the white label complete_booking API:

GET https://demo-stripe.ticketswitch.com/api/complete_booking/<transaction_uuid>/?trolley_token=<token>&referer_url=<referer_url>
Parameter Description
transaction_uuid The unique reference for the reserved tickets, taken from the reserve response. May also be provided as a GET query string parameter.
trolley_token The trolley_token used to create the reservation. Optional.
referer_url The URL of the page from which your customer is coming (mispelling in line with the HTTP specification). If not specified it will be taken from the request header. Used to send the customer back to you if they request a change in their booking details. Optional.

After the purchase has completed, on the demo-stripe white label the customer is taken to the White Label’s confirmation page at https://demo-stripe.ticketswitch.com/confirmation/<transaction_uuid>/ - this behaviour is customisable and we can redirect the customer to any URL containing the transaction_uuid as a parameter.

Direct integration to the Ingresso payments API

In order to purchase with Stripe directly you need the following steps:

  1. Retrieve the Stripe PaymentIntent ID and client secret from the reservation response in the bundle.debitor.debitor_integration_data.stripe section
  2. Update the PaymentIntent as per the Stripe API docs
  3. Call purchase.v1 passing in the PaymentIntent reference from step 2.

Note that you need to retrieve and pass in one payment parameter for each bundle that you reserve. If you only support the purchase of one item at a time, or if you don’t use the Ingresso API to help manage basketing then you can ignore this but it is a requirement for proper bundling support.

Updating the Stripe PaymentIntent

You will need to provide Stripe with the appropriate publishable key - this is returned by Ingresso in the reserve call as bundle.debitor.debitor_integration_data.stripe.publishable_key.

Follow the Stripe PaymentIntents Guide for how to use a PaymentIntent with Stripe.js to ensure your integration is compatible with PCI-DSS and customer payment card information is kept secure.

EOF “`

# We suggest Javascript integration on the front end, but you can use
# a HTTP requests library if you'd prefer.
const integration_data = {
    cider_api_endpoint: "https://payments.ingresso.co.uk/api",
    cider_api_token: "key_XYZ789123",
    stripe: {
        payment_intent: "pi_test",
        client_secret: "secret"
    }
};

// get Stripe PaymentIntent and update it using the Stripe.js API
let stripePaymentIntent = integration_data.stripe.payment_intent;

const http = new XMLHttpRequest();
http.open('POST', integration_data.cider_api_endpoint + '/save-details', true);
http.setRequestHeader('Content-type', 'application/json');
http.setRequestHeader('Authorization', 'Bearer ' + integration_data.cider_api_key);
http.onload = () => {
    if (http.status === 200) {
        // get token from response
    } else {
        // handle error
    }
};
http.onerror = () => console.log("Unable to connect");
http.ontimeout = () => console.log("Connection timed out.");
http.send(JSON.stringify({ stripe_payment_intent: stripePaymentIntent }));

Example response

{"token": "cider_XYZ789123"}

Once you have updated the Stripe PaymentIntent, you must save it in Ingresso’s payment processing Engine (called Cider). The API endpoint you can use is also found in the reserve call integration data, as bundle.debitor.debitor_integration_data.cider_api_endpoint. You will need to use a unique key per reservation, found at debitor_integration_data.cider_api_token.

The API endpoint will look something like https://payments.ingresso.co.uk/api and you can save the stripe payment intent generated above by making a HTTP POST request to this endpoint + /save-details, and authenticating with the key provided in the integration data.

In addition to saving stripe data and payment sources, you can also save metadata about the purchase to this endpoint, which will be saved in Stripe against the purchase record. This is very important for anti-fraud rules when using the Ingresso Stripe account, and may be useful for your own account too.

You must pass in the actual customer’s remote_ip if you are taking payment via Ingresso’s Stripe account - we use this for fraud checks. It is also useful to pass in the remote_site so we know which website the customer purchased on.

One primary advantage of saving the details in this way is that it will not appear in Ingresso’s logs or database, and is only used as metadata in Stripe, so it reduces the spread of personally identifiable information. Please note that the call must include a valid Authorization header with the key included in the reservation response debitor integration data, and should be well-formed JSON, as per the examples.

Making the purchase call

Updating the Stripe PaymentIntent is the first half of the payment process - further server-side code is required to complete the second half. You don’t need to worry about this as Ingresso’s payment processor takes care of it. Once you have saved the Stripe token and retrieved the cider token, we will handle the following steps:

Purchase request

Example purchase request - Stripe

curl https://api.ticketswitch.com/f13/purchase.v1 \
    -u "demo-stripe:demopass" \
    -d "transaction_uuid=2e740db5-1b65-11e7-9e97-002590326932" \
    -d "first_name=Test" \
    -d "last_name=Tester" \
    -d "address_line_one=Metro Building" \
    -d "address_line_two=1 Butterwick" \
    -d "town=London" \
    -d "county=London" \
    -d "postcode=W6 8DL" \
    -d "country_code=uk" \
    -d "phone=0203 137 7420" \
    -d "email_address=tester@gmail.com" \
    -d "ext_test0_callback/cider_token=cider_XYZ789123" \
    -d "send_confirmation_email=yes" \
    -d "remote_ip=101.102.103.104" \
    -d "remote_site=www.myticketshop.com" \
    --compressed \
    -X POST
from pyticketswitch import Client
from pyticketswitch.customer import Customer
from pyticketswitch.payment_methods import CiderDetails


client = Client('demo-stripe', 'demopass')

customer = Customer(
    first_name='Test',
    last_name='Tester',
    address_lines=['Metro Building', '1 Butterwick'],
    town='London',
    county='London',
    post_code='W6 8DL',
    country_code='uk',
    phone='0203 137 7420',
    email='testing@gmail.com',
    user_can_use_customer_data=True,
)

cider_details = CiderDetails(
    {'cider_token': 'cider_XYZ789123'},
    ['ext_test0'],
)

status, callout, meta = client.make_purchase(
    '7150d25f-301b-11e7-bede-0025903268a0',
    customer,
    payment_method=cider_details,
    send_confirmation_email=True,
)

To complete a test Stripe purchase:

  1. Call reserve
  2. Enter test card details into the Stripe Elements example form and copy the Stripe token returned.
  3. Save the Stripe token in the Ingresso Payments processing service (Cider)
  4. Call purchase, replacing the transaction_uuid and ext_test0_callback/cider_token with the values from the 3 steps above.

All of the parameters mentioned above in the purchasing on credit section are used. In addition the following parameter should be specified:

Parameter Description
remote_ip The end customer’s IP address.
remote_site The website the end customer is purchasing from, not including https:// or http://.
X_callback/cider_token The single-use token retrieved from Cider after saving the Stripe payment intent being used. You should replace X with the source_code returned by reserve. So for source_code=ext_test0 the parameter name used is ext_test0_callback/cider_token. If you support basketing and your customer is attempting to purchase items across multiple bundles, you should provide the same Cider token for each bundle (each bundle has a unique source_code).

Purchase response

Example purchase response - Stripe

{
  "currency_details": {
    "gbp": {
      "currency_code": "gbp",
      "currency_factor": 100,
      "currency_number": 826,
      "currency_places": 2,
      "currency_post_symbol": "",
      "currency_pre_symbol": "£"
    }
  },
  "customer": {
    "addr_line_one": "Metro Building",
    "addr_line_one_latin": "Metro Building",
    "addr_line_two": "1 Butterwick",
    "addr_line_two_latin": "1 Butterwick",
    "agent_ref": "",
    "country": "United Kingdom",
    "country_code": "uk",
    "country_latin": "United Kingdom",
    "county": "",
    "county_latin": "",
    "dp_supplier": false,
    "dp_user": false,
    "dp_world": false,
    "email_addr": "tester@gmail.com",
    "first_name": "Test",
    "first_name_latin": "Test",
    "home_phone": "0203 137 7420",
    "initials": "",
    "initials_latin": "",
    "last_name": "Tester",
    "last_name_latin": "Tester",
    "postcode": "W6 8DL",
    "postcode_latin": "W6 8DL",
    "suffix": "",
    "suffix_latin": "",
    "title": "",
    "title_latin": "",
    "town": "London",
    "town_latin": "London",
    "work_phone": "0203 137 7420"
  },
  "language_list": "en-gb,en,en-us,nl",
  "purchase_iso8601_date_and_time": "2017-03-03T15:58:26Z",
  "reserve_iso8601_date_and_time": "2017-03-03T15:58:01Z",
  "transaction_status": "purchased",
  "trolley_contents": {
    "bundle": [
      {
        "bundle_order_count": 1,
        "bundle_source_code": "ext_test0",
        "bundle_source_desc": "External Test Backend 0",
        "bundle_total_cost": 62.5,
        "bundle_total_seatprice": 51,
        "bundle_total_send_cost": 1.5,
        "bundle_total_surcharge": 10,
        "currency_code": "gbp",
        "order": [
          {
            "backend_purchase_reference": "PURCHASE-17BB2-1",
            "cancellation_comment" : "",
            "cancellation_status" : "possible",
            "event": {
              "city_code": "london-uk",
              "city_desc": "London",
              "classes": {
                "dance": "Ballet & Dance"
              },
              "country_code": "uk",
              "country_desc": "United Kingdom",
              "critic_review_percent": 100,
              "custom_filter": [],
              "event_desc": "Matthew Bourne's Nutcracker TEST",
              "event_id": "6IF",
              "event_path": "/6IF-matthew-bourne-s-nutcracker-test/",
              "event_status": "live",
              "event_type": "simple_ticket",
              "event_upsell_list": {
                "event_id": [
                  "6IE",
                  "MH0"
                ]
              },
              "event_uri_desc": "Matthew-Bourne%27s-Nutcracker-TEST",
              "geo_data": {
                "latitude": 51.52961137,
                "longitude": -0.10601562
              },
              "has_no_perfs": false,
              "is_seated": true,
              "max_running_time": 120,
              "min_running_time": 120,
              "need_departure_date": false,
              "need_duration": false,
              "need_performance": true,
              "postcode": "EC1R 4TN",
              "show_perf_time": true,
              "source_code": "ext_test0",
              "source_desc": "External Test Backend 0",
              "user_review_percent": 100,
              "venue_desc": "Sadler's Wells",
              "venue_uri_desc": "Sadler%27s-Wells"
            },
            "got_requested_seats": false,
            "gross_commission": {
              "amount_excluding_vat": 7.13,
              "amount_including_vat": 8.55,
              "commission_currency_code": "gbp"
            },
            "item_number": 1,
            "performance": {
              "date_desc": "Tue, 13th June 2017",
              "event_id": "6IF",
              "has_pool_seats": true,
              "is_ghost": false,
              "is_limited": false,
              "iso8601_date_and_time": "2017-06-13T19:30:00+01:00",
              "perf_id": "6IF-B1S",
              "perf_name": "Including back stage pass",
              "running_time": 120,
              "time_desc": "7.30 PM"
            },
            "price_band_code": "C/pool",
            "send_method": {
              "send_code": "COBO",
              "send_cost": 1.5,
              "send_desc": "Collect from the venue",
              "send_final_type": "collect",
              "send_type": "collect"
            },
            "supported_barcode_types": [
              "qr_code"
            ],
            "ticket_orders": {
              "ticket_order": [
                {
                  "discount_code": "ADULT",
                  "discount_desc": "Adult",
                  "no_of_seats": 1,
                  "sale_seatprice": 25,
                  "sale_surcharge": 4,
                  "seats": [
                    {
                      "col_id": "419",
                      "full_id": "OR419",
                      "is_restricted_view": false,
                      "row_id": "OR"
                    }
                  ],
                  "total_sale_seatprice": 25,
                  "total_sale_surcharge": 4
                },
                {
                  "discount_code": "CHILD",
                  "discount_desc": "Child rate",
                  "no_of_seats": 2,
                  "sale_seatprice": 13,
                  "sale_surcharge": 3,
                  "seats": [
                    {
                      "col_id": "416",
                      "full_id": "OR416",
                      "is_restricted_view": false,
                      "row_id": "OR"
                    },
                    {
                      "col_id": "413",
                      "full_id": "OR413",
                      "is_restricted_view": false,
                      "row_id": "OR"
                    }
                  ],
                  "total_sale_seatprice": 26,
                  "total_sale_surcharge": 6
                }
              ]
            },
            "ticket_type_code": "CIRCLE",
            "ticket_type_desc": "Upper circle",
            "total_no_of_seats": 3,
            "total_sale_seatprice": 51,
            "total_sale_surcharge": 10,
            "user_commission": {
              "amount_excluding_vat": 0,
              "amount_including_vat": 0,
              "commission_currency_code": "gbp"
            }
          }
        ],
        "purchase_result": {
          "is_semi_credit": false,
          "success": true
        }
      }
    ],
    "purchase_result": {
      "is_partial": false,
      "success": true
    },
    "transaction_id": "T000-0000-8N66-K30B",
    "transaction_uuid": "2dac0d00-002a-11e7-975c-002590326962",
    "trolley_bundle_count": 1,
    "trolley_order_count": 1
  }
}
from pyticketswitch.customer import Customer
from pyticketswitch.trolley import Trolley
from pyticketswitch.debitor import Debitor
from pyticketswitch.status import Status
from pyticketswitch.seat import Seat
from pyticketswitch.performance import Performance
from pyticketswitch.order import TicketOrder
from pyticketswitch.purchase_result import PurchaseResult
from pyticketswitch.event import Event
from pyticketswitch.send_method import SendMethod
from pyticketswitch.order import Order
from pyticketswitch.bundle import Bundle

# stripe purchases should always return a status object, and no callout.
Status(
    status='purchased',
    reserved_at=datetime.datetime(2017, 5, 3, 16, 13, 28, tzinfo=tzutc()),
    purchased_at=datetime.datetime(2017, 5, 3, 16, 14, 19, tzinfo=tzutc()),
    trolley=Trolley(
        transaction_uuid='7150d25f-301b-11e7-bede-0025903268a0',
        transaction_id='T000-0000-8ZW5-68A8',
        bundles=[
            Bundle(
                source_code='ext_test0',
                orders=[
                    Order(
                        item=1,
                        cancellation_comment='',
                        cancellation_status='possible',
                        event=Event(
                            id='6IF',
                            status='live',
                            description="Matthew Bourne's Nutcracker TEST",
                            source='External Test Backend 0',
                            source_code='ext_test0',
                            event_type='simple_ticket',
                            venue="Sadler's Wells",
                            classes={
                                'dance': 'Ballet & Dance'
                            },
                            filters=[

                            ],
                            postcode='EC1R 4TN',
                            city='London',
                            city_code='london-uk',
                            country='United Kingdom',
                            country_code='uk',
                            latitude=51.52961137,
                            longitude=-0.10601562,
                            max_running_time=120,
                            min_running_time=120,
                            show_performance_time=True,
                            has_performances=True,
                            is_seated=True,
                            needs_departure_date=False,
                            needs_duration=False,
                            needs_performance=False,
                            upsell_list=[
                                '6IE',
                                'MH0'
                            ],
                            critic_review_percent=100,
                        ),
                        performance=Performance(
                            id='6IF-B0O',
                            event_id='6IF',
                            date_time=datetime.datetime(2017, 5, 4, 19, 30, tzinfo=tzoffset(None, 3600)),
                            date_description='Thu, 4th May 2017',
                            time_description='7.30 PM',
                            has_pool_seats=True,
                            is_limited=False,
                            is_ghost=False,
                            running_time=120,
                        ),
                        price_band_code='A/pool',
                        ticket_type_code='STALLS',
                        ticket_type_description='Stalls',
                        ticket_orders=[
                            TicketOrder(
                                code='',
                                seats=[
                                    Seat(
                                        id='JM189',
                                        column='189',
                                        row='JM',
                                        separator='',
                                        is_restricted=False,
                                    ),
                                    Seat(
                                        id='JM190',
                                        column='190',
                                        row='JM',
                                        separator='',
                                        is_restricted=False,
                                    )
                                ],
                                description='',
                                number_of_seats=2,
                                seatprice=21.0,
                                surcharge=3.0,
                                total_seatprice=42.0,
                                total_surcharge=6.0,
                            )
                        ],
                        number_of_seats=2,
                        total_seatprice=42.0,
                        total_surcharge=6.0,
                        seat_request_status='not_requested',
                        requested_seat_ids=[

                        ],
                        backend_purchase_reference='PURCHASE-11F22-1',
                        send_method=SendMethod(
                            code='COBO',
                            cost=1.5,
                            description='Collect from the venue',
                            type='collect',
                        ),
                    )
                ],
                description='External Test Backend 0',
                total_seatprice=42.0,
                total_surcharge=6.0,
                total_send_cost=1.5,
                total=49.5,
                currency_code='gbp',
                debitor=Debitor(
                    type='cider',
                    name='cider',
                    description='Cider',
                    integration_data={
                        'cider_api_token': 'key_XYZ789123',
                        'cider_api_endpoint': 'https://payments.ingresso.co.uk/api',
                        'cider_js': 'https://payments.ingresso.co.uk/static/js/cider/cider.js',
                        'merchant_group_country_code': 'gb',
                        'stripe': {
                            'publishable_key': 'pk_test_b7N9DOwbo4B9t6EqCf9jFzfa',
                            'payment_sources_enabled': true,
                            'required': true,
                        },
                    },
                ),
            )
        ],
        discarded_orders=[

        ],
        purchase_result=PurchaseResult(
            success=True,
        ),
    ),
    languages=[
        'en'
    ],
    customer=Customer(
        first_name='Test',
        first_name_latin='Test',
        last_name='Tester',
        last_name_latin='Tester',
        address_lines=[
            'Metro Building',
            '1 Butterwick'
        ],
        address_lines_latin=[
            'Metro Building',
            '1 Butterwick'
        ],
        title='',
        title_latin='',
        initials='',
        initials_latin='',
        suffix='',
        suffix_latin='',
        country_code='uk',
        post_code='W6 8DL',
        post_code_latin='W6 8DL',
        town='London',
        town_latin='London',
        county='London',
        county_latin='London',
        country='United Kingdom',
        country_latin='United Kingdom',
        email='testing@gmail.com',
        home_phone='0203 137 7420',
        work_phone='0203 137 7420',
        agent_reference='',
    ),
)

The response is identical to the purchase response described in purchasing on credit, with some additional information about the debitor result to aid with handling payment failures.

As the process and certification of an integration with Ingresso Payments and Stripe can be quite challenging, it is highly recommended that partners use the Ingresso White Label checkout component as part of their solution as this is tested and maintained.

Purchasing with redirect

This section describes how to handle generic redirects which are needed for other supported payment providers such as Global Collect. The vast majority of partners are either on-credit or Stripe, and so will use the payment methods mentioned above, but this supporting this method is recommended where possible.

Redirects are required when:

To support generic redirects you should use the following sequence:

  1. Call the purchase endpoint
  2. The Ingresso platform will determine whether you need to redirect your customer. If so the response will include a callout section with the information you need to redirect your customer.
  3. Redirect your customer to callout_destination_url, including the callout_parameters in the query string (they must be URL encoded).
  4. After the redirect your customer will arrive back at your return_url, and you may receive query string or post parameters.
  5. You should then call the callback endpoint, passing in verbatim all query string and post parameters you have received. These are needed by Ingresso to for example finalise the payment collection.
  6. If any further redirects are required, the callback response will include a callout section. You should continue to follow steps 3, 4 and 5 until the callback response no longer includes a callout section. At this point the purchase will be complete (it will have either succeeded or failed).

Please note as an alternative to the integration steps above, the Ingresso Payments solution may also be used as a generic redirect, in which case the payment page will be presented by the Ingresso payment service directly.

Purchase request

Example purchase request - generic redirects

curl https://api.ticketswitch.com/f13/purchase.v1 \
    -u "demo-redirect:demopass" \
    -d "transaction_uuid=a75a03c3-efc2-11e6-a96d-d0bf9c45f5c0" \
    -d "first_name=Test" \
    -d "last_name=Tester" \
    -d "address_line_one=Metro Building" \
    -d "address_line_two=1 Butterwick" \
    -d "town=London" \
    -d "county=London" \
    -d "postcode=W6 8DL" \
    -d "country_code=uk" \
    -d "phone=0203 137 7420" \
    -d "email_address=tester@gmail.com" \
    -d "return_token=FIRST_RANDOM_TOKEN" \
    -d "return_url=https://www.yourticketingsite.com/token.FIRST_RANDOM_TOKEN/return.php" \
    -d "client_http_user_agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/602.4.8 (KHTML, like Gecko) Version/10.0.3 Safari/602.4.8" \
    -d "client_http_accept=text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" \
    -d "send_confirmation_email=yes" \
    -d "privacy_policy_version=2.2.1" \
    -X POST
import uuid
from pyticketswitch import Client
from pyticketswitch.customer import Customer
from pyticketswitch.payment_methods import RedirectionDetails


client = Client('demo-redirect', 'demopass')

customer = Customer(
    first_name='Test',
    last_name='Tester',
    address_lines=['Metro Building', '1 Butterwick'],
    town='London',
    county='London',
    post_code='W6 8DL',
    country_code='uk',
    phone='0203 137 7420',
    email='testing@gmail.com',
    user_can_use_customer_data=True,
)

token = uuid.uuid4()

redirect_details = RedirectionDetails(
    token=token,
    url='https://www.fromtheboxoffice.com/callback/{}'.format(token),
    user_agent='Mozilla/5.0 (X11; Linux x86_64; rv:51.0) Gecko/20100101 Firefox/51.0',
    accept='text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    remote_site='www.fromtheboxoffice.com',
)

status, callout, meta = client.make_purchase(
    '7150d25f-301b-11e7-bede-0025903268a0',
    customer,
    payment_method=redirect_details,
    send_confirmation_email=True,
)

All of the parameters mentioned above in the purchasing on credit section are used. In addition the following parameters must be specified:

Parameter Description
return_token This token must be alphanumeric with -, _ and . also allowed. We recommend that partners generate a UUID for this token.
return_url The URL that your customer should arrive back to after being redirected. The return_token also has to be present in the path for the return_url and no query string parameters are allowed in the return_url.
client_http_user_agent The user agent, taken from the headers of your customer’s web browser. This and client_http_accept are required because the payment provider that generates the callout may need to know detail of the browser, for example to serve a mobile-optimised page.
client_http_accept The accept content types, from the headers of your customer’s web browser.

Purchase response

Example purchase response - generic redirects

{
  "callout": {
    "callout_destination_url": "https://api.ticketswitch.com/tickets/dummy_redirect.buy/demo-redirect",
    "callout_parameters": {
      "return_url": "https://www.yourticketingsite.com/token.FIRST_UNIQUE_TOKEN/return.php",
      "title": "Dummy external card details page for debit on system 'ext_test0'"
    },
    "callout_parameters_order": [],
    "callout_type": "get",
    "debitor_integration_data": {
      "debit_amount": 62.5,
      "debit_base_amount": 6250,
      "debit_currency": "gbp",
      "debitor_specific_data": {
        "is_dummy_3d_secure": false
      },
      "debitor_type": "dummy"
    }
  },
  "currency_details": {
    "gbp": {
      "currency_code": "gbp",
      "currency_factor": 100,
      "currency_number": 826,
      "currency_places": 2,
      "currency_post_symbol": "",
      "currency_pre_symbol": "£"
    }
  }
}
from pyticketswitch.debitor import Debitor
from pyticketswitch.callout import Callout

# redirect purchases may return either a status object or a callout object
# when they requirement more information from the user.
Callout(
    code='ext_test0',
    description='External Test Backend 0',
    total=49.5,
    type='get',
    destination='https://www.fromtheboxoffice.com/tickets/dummy_redirect.buy/demo-redirect',
    parameters={
        'return_url': 'https://www.fromtheboxoffice.com/callback/64e8a0d8-ca3a-4a3b-8a39-597ee66acdd0',
        'title': "Dummy external card details page for debit on system 'ext_test0'"
    },
    integration_data={
        'is_dummy_3d_secure': False
    },
    debitor=Debitor(
        type='dummy',
        name='dummy',
        description='The Dummy Card Debitor',
        integration_data={},
    ),
    currency_code='gbp',
    return_token='64e8a0d8-ca3a-4a3b-8a39-597ee66acdd0',
)
Attribute Description
callout See below for object detail.
currency_details Further details of the currencies found in the callout data.

callout attributes:

Attribute Description
callout_destination_url The URL you should redirect your customer to.
callout_parameters The parameters that should be passed. The callout_type will specify whether to use GET or POST.
callout_parameters_order In most cases this will be blank, and it can be ignored. In very rare cases, for callout_type=get, it will include all callout_parameters in a specific order - you should then specify the parameters in that order.
callout_type Whether you should make a GET or POST request.
debitor_integration_data This data is not needed when redirecting (so is not of use to most partners). It provides information needed to avoid redirecting.

Callback request

Example callback request - generic redirects

curl https://api.ticketswitch.com/f13/callback.v1/this.FIRST_UNIQUE_TOKEN/next.NEXT_UNIQUE_TOKEN \
    -u "demo-redirect:demopass" \
    -d "param1=asdfasdfsdfasdff" \
    -r "https://www.thepaymentpage.com/asdfsadfsdafasdf" \
    --compressed
    -X POST
import uuid
from pyticketswitch import Client

client = Client('demo-redirect', 'demopass')

returned_data = {'success': 'yes'}
next_token = uuid.uuid4()
status, callout, meta = client.next_callout(
    '64e8a0d8-ca3a-4a3b-8a39-597ee66acdd0',
    next_token,
    returned_data,
)

If the purchase response received includes callout data then you need to redirect your customer and afterwards use the callback endpoint.

Note that the URL structure is callback.v1/this.[previous token used]/next.[new token]. If purchase was the last endpoint hit, then the “previous token used” is the return_token that was passed in to purchase. If the last endpoint hit was callback then “previous token used” is the “new token” you generated for the previous callback.

You should pass the payment page URL you have been referred from as the Referrer in the headers.

You should pass in verbatim all query string and post parameters you have received. These are needed by Ingresso to for example finalise the payment collection.

The callback response will either:

You should continue to call callback until you no longer see callout data.

Reserve Page Archive

Definition

GET https://api.ticketswitch.com/f13/reserve_page_archive.v1

This API call does not get an up to date status of the reservation, it is simply retrieving the previously sent reservation response, verbatim. Reservation responses are held for 24 hours, this exceeds the length of time that reservations are valid for. Do not interpret this response as meaning that a reservation is still being held as it is simply a verbatim copy of the original reservation response. This means that you can access all the data that you would normally require from a status call, except that the status and the amount of time left on the reservation will not have been updated (as it will be exactly the same as the original reservation response). As this is simply returning a verbatim copy of the original reservation response, HTTP content negotiation and any of the usually recognised req_ variables will be ignored. If the original reservation response was an error then the same error will be returned when you request the reserve page archive. If the reservation is not found then you will get an 400 error with error_code: 8. If the reservation is no longer being stored (i.e. more than 24 hours have passed since the original reservation was made) you will get a 410 Gone error with error_code: 8.

Request

Example request

curl https://api.ticketswitch.com/f13/reserve_page_archive.v1 \
    -u "demo:demopass" \
    -d "transaction_uuid=U-986E1961-F8B7-11E8-8434-AC1F6B465FBC-C7DCDC47-LDNX" \
    --compressed \
    -G
from pyticketswitch import Client

client = Client('demo', 'demopass')
reservation, meta = client.get_reservation(
    transaction_uuid="U-986E1961-F8B7-11E8-8434-AC1F6B465FBC-C7DCDC47-LDNX"
)
Parameter Description
transaction_uuid The unique identifier returned by a previous reserve.

Response

Example response - get a previously made reserve response


{
   "needs_payment_card" : false,
   "unreserved_orders" : [],
   "allowed_countries" : {
      "uk" : "United Kingdom"
   },
   "reserve_iso8601_date_and_time" : "2018-12-05T18:00:05Z",
   "transaction_status" : "reserved",
   "language_list" : [
      "en"
   ],
   "input_contained_unavailable_order" : false,
   "needs_agent_reference" : false,
   "minutes_left_on_reserve" : 15,
   "currency_details" : {
      "gbp" : {
         "currency_number" : 826,
         "currency_factor" : 100,
         "currency_code" : "gbp",
         "currency_pre_symbol" : "£",
         "currency_post_symbol" : "",
         "currency_places" : 2
      }
   },
   "needs_email_address" : false,
   "trolley_contents" : {
      "trolley_bundle_count" : 1,
      "transaction_uuid" : "U-986E1961-F8B7-11E8-8434-AC1F6B465FBC-C7DCDC47-LDNX",
      "bundle" : [
         {
            "bundle_total_send_cost" : 1,
            "bundle_source_code" : "ext_test1",
            "currency_code" : "gbp",
            "order" : [
               {
                  "internal_reserve_sub_ref" : "",
                  "total_no_of_seats" : 3,
                  "total_sale_seatprice" : 150,
                  "item_number" : 1,
                  "ticket_orders" : {
                     "ticket_order" : [
                        {
                           "sale_surcharge" : 5,
                           "sale_seatprice" : 50,
                           "total_sale_seatprice" : 150,
                           "total_sale_surcharge" : 15,
                           "discount_desc" : "Regular Ticket",
                           "no_of_seats" : 3,
                           "discount_code" : "NORMAL",
                           "seats" : [
                              {
                                 "col_id" : "2",
                                 "full_id" : "B2",
                                 "is_restricted_view" : false,
                                 "row_id" : "B",
                                 "seat_text_code" : "B.2"
                              },
                              {
                                 "is_restricted_view" : false,
                                 "col_id" : "3",
                                 "full_id" : "B3",
                                 "seat_text_code" : "B.3",
                                 "row_id" : "B"
                              },
                              {
                                 "col_id" : "4",
                                 "full_id" : "B4",
                                 "is_restricted_view" : false,
                                 "seat_text_code" : "B.4",
                                 "row_id" : "B"
                              }
                           ]
                        }
                     ]
                  },
                  "price_band_code" : "A/pool",
                  "ticket_type_desc" : "Stalls",
                  "event" : {
                     "is_auto_quantity_add_on" : false,
                     "city_code" : "london-uk",
                     "event_type" : "simple_ticket",
                     "custom_filter" : [],
                     "need_duration" : false,
                     "event_uri_desc" : "TEST-EVENT-The-Unremarkable-Incident-of-the-Cat-at-Lunchtime",
                     "venue_uri_desc" : "Lyric-Apollo",
                     "venue_desc" : "Lyric Apollo",
                     "event_id" : "7AB",
                     "event_desc" : "TEST EVENT - The Unremarkable Incident of the Cat at Lunchtime",
                     "is_seated" : true,
                     "postcode" : "W6 7ES",
                     "event_upsell_list" : {
                        "event_id" : [
                           "7AA",
                           "6IF"
                        ]
                     },
                     "country_code" : "uk",
                     "need_departure_date" : false,
                     "classes" : {
                        "tours" : "Tours"
                     },
                     "min_running_time" : 90,
                     "event_status" : "live",
                     "source_code" : "ext_test1",
                     "city_desc" : "London",
                     "has_no_perfs" : false,
                     "show_perf_time" : true,
                     "is_add_on" : false,
                     "need_performance" : true,
                     "country_desc" : "United Kingdom",
                     "max_running_time" : 90,
                     "source_desc" : "External Test Backend 1",
                     "geo_data" : {
                        "latitude" : 51.49306,
                        "longitude" : -0.22639
                     },
                     "event_path" : "/7AB-test-event-the-unremarkable-incident-of-the-cat-at-lunchtime/"
                  },
                  "performance" : {
                     "time_desc" : "3.30 PM",
                     "has_pool_seats" : true,
                     "is_limited" : false,
                     "iso8601_date_and_time" : "2020-01-01T15:30:00Z",
                     "is_ghost" : false,
                     "event_id" : "7AB",
                     "date_desc" : "Wed, 1st January 2020",
                     "running_time" : 90,
                     "perf_id" : "7AB-6"
                  },
                  "send_method" : {
                     "can_generate_self_print" : false,
                     "send_desc" : "Printable eTicket",
                     "send_cost" : 1,
                     "has_html_page" : true,
                     "send_type" : "selfprint",
                     "send_code" : "VOUCH"
                  },
                  "seat_request_status" : "not_requested",
                  "total_sale_surcharge" : 15,
                  "ticket_type_code" : "STALLS",
                  "requested_seat_ids" : []
               }
            ],
            "bundle_total_cost" : 166,
            "bundle_total_surcharge" : 15,
            "bundle_order_count" : 1,
            "bundle_total_seatprice" : 150,
            "bundle_source_desc" : "External Test Backend 1"
         }
      ],
      "trolley_order_count" : 1
   },
   "can_edit_address" : true,
   "prefilled_address" : {
      "country_code" : "uk"
   }
}
from pyticketswitch.send_method import SendMethod
from pyticketswitch.country import Country
from pyticketswitch.seat import Seat
from pyticketswitch.address import Address
from pyticketswitch.event import Event
from pyticketswitch.bundle import Bundle
from pyticketswitch.performance import Performance
from pyticketswitch.reservation import Reservation
from pyticketswitch.order import TicketOrder
from pyticketswitch.trolley import Trolley
from pyticketswitch.order import Order

Reservation(
    status='reserved',
    reserved_at=datetime.datetime(2017, 5, 3, 15, 1, 45, tzinfo=tzutc()),
    trolley=Trolley(
        transaction_uuid='U-986E1961-F8B7-11E8-8434-AC1F6B465FBC-C7DCDC47-LDNX',
        bundles=[
            Bundle(
                source_code='ext_test1',
                orders=[
                    Order(
                        item=1,
                        event=Event(
                            id='7AB',
                            status='live',
                            description='The Unremarkable Incident of the Cat at Lunchtime'
,
                            source='External Test Backend 1',
                            source_code='ext_test1',
                            event_type='simple_ticket',
                            venue='Lyric Apollo',
                            classes={
                                'theatre': 'Theatre'
                            },
                            postcode='W6 7ES',
                            city='London',
                            city_code='london-uk',
                            country='United Kingdom',
                            country_code='uk',
                            latitude=51.49306,
                            longitude=-0.22639,
                            max_running_time=90,
                            min_running_time=90,
                            show_performance_time=True,
                            has_performances=True,
                            is_seated=True,
                            needs_departure_date=False,
                            needs_duration=False,
                            needs_performance=False,
                        ),
                        performance=Performance(
                            id='7AB-5',
                            event_id='7AB',
                            date_time=datetime.datetime(2019, 1, 1, 15, 30, tzinfo=tzutc()) ,
                            date_description='Tue, 1st January 2019',
                            time_description='3.30 PM',
                            has_pool_seats=True,
                            is_limited=False,
                            is_ghost=False,
                            running_time=90,
                        ),
                        price_band_code='A/pool',
                        ticket_type_code='STALLS',
                        ticket_type_description='Stalls',
                        ticket_orders=[
                            TicketOrder(
                                code='NORMAL',
                                seats=[
                                    Seat(
                                        id='A1',
                                        column='1',
                                        row='A',
                                        separator='',
                                        is_restricted=True,
                                        seat_text='Restricted View',
                                    ),
                                    Seat(
                                        id='A2',
                                        column='2',
                                        row='A',
                                        separator='',
                                        is_restricted=True,
                                        seat_text='Restricted View',
                                    )
                                ],
                                description='Regular Ticket',
                                number_of_seats=2,
                                seatprice=50.0,
                                surcharge=5.0,
                                total_seatprice=100.0,
                                total_surcharge=10.0,
                            )
                        ],
                        number_of_seats=2,
                        total_seatprice=100.0,
                        total_surcharge=10.0,
                        seat_request_status='got_all',
                        requested_seat_ids=[
                            'A1',
                            'A2'
                        ],
                        send_method=SendMethod(
                            code='VOUCH',
                            cost=0.0,
                            description='Printable eTicket',
                            type='selfprint',
                            can_generate_self_print=False,
                        ),
                    )
                ],
                description='External Test Backend 1',
                total_seatprice=100.0,
                total_surcharge=10.0,
                total_send_cost=0.0,
                total=110.0,
                currency_code='gbp',
            )
        ],
        minutes_left=14.9833333333,
    ),
    languages=[
        'en'
    ],
    needs_payment_card=False,
    needs_email_address=False,
    needs_agent_reference=False,
    can_edit_address=True,
    allowed_countries=[
        Country(
            code='uk',
            description='United Kingdom',
        )
    ],
    minutes_left=14.9833333333,
)

The returned attributes are identical to the original reserve response, even if the reservation has timed out or has been bought, this response will stay the same.

Attribute Description
reserve_iso8601_date_and_time The time the tickets were successfully reserved.
transaction_status Will always be reserved as that is what it was at the time of the reservation, even if the transaction has since expired or been purchased.
trolley The trolley object, the trolley attributes are as described in the reserve response. Note that the value of minutes_left_on_reserve will be out of date as it will be the same as it was at reserve time.

Purchase Page Archive

Definition

GET https://api.ticketswitch.com/f13/purchase_page_archive.v1

This API call does not get an up to date status of the purchase, it is simply retrieving the previously sent purchase response, verbatim. This means that you can access all the data that you would normally require from a purchase call, except that the status could be out of date (as it will be exactly the same as the original purchase response). As this is simply returning a verbatim copy of the original purchase response, HTTP content negotiation and any of the usually recognised req_ variables will be ignored. If the original purchase response was an error then the same error will be returned when you request the purchase page archive. The purchase responses are kept for at least a year. If the purchase is not found then you will get an 400 error with error_code: 8. If the purchase is no longer being stored (i.e. more than a year has passed since the original purchase was made) you will get a 410 Gone error with error_code: 8.

Request

Example request

curl https://api.ticketswitch.com/f13/purchase_page_archive.v1 \
    -u "demo:demopass" \
    -d "transaction_uuid=U-986E1961-F8B7-11E8-8434-AC1F6B465FBC-C7DCDC47-LDNX" \
    --compressed \
    -G
from pyticketswitch import Client

client = Client('demo', 'demopass')
reservation, meta = client.get_purchase(
    transaction_uuid="U-986E1961-F8B7-11E8-8434-AC1F6B465FBC-C7DCDC47-LDNX"
)
Parameter Description
transaction_uuid The unique identifier returned by a previous purchase.

Response

Example response - a previously purchased transaction

{
  "currency_details": {
    "gbp": {
      "currency_code": "gbp",
      "currency_factor": 100,
      "currency_number": 826,
      "currency_places": 2,
      "currency_post_symbol": "",
      "currency_pre_symbol": "£"
    }
  },
  "customer": {
    "addr_line_one": "Metro Building",
    "addr_line_one_latin": "Metro Building",
    "addr_line_two": "1 Butterwick",
    "addr_line_two_latin": "1 Butterwick",
    "agent_ref": "",
    "country": "United Kingdom",
    "country_code": "uk",
    "country_latin": "United Kingdom",
    "county": "",
    "county_latin": "",
    "email_addr": "testing@gmail.com",
    "first_name": "Test",
    "first_name_latin": "Test",
    "home_phone": "0203 137 7420",
    "initials": "",
    "initials_latin": "",
    "last_name": "Tester",
    "last_name_latin": "Tester",
    "postcode": "W6 8DL",
    "postcode_latin": "W6 8DL",
    "suffix": "",
    "suffix_latin": "",
    "supplier_can_use_customer_data": false,
    "title": "",
    "title_latin": "",
    "town": "London",
    "town_latin": "London",
    "user_can_use_customer_data": true,
    "work_phone": "0203 137 7420",
    "world_can_use_customer_data": false
  },
  "language_list": [
    "en-gb",
    "en",
    "en-us",
    "nl"
  ],
  "purchase_iso8601_date_and_time": "2017-04-12T08:38:35Z",
  "reserve_iso8601_date_and_time": "2017-04-12T08:38:20Z",
  "transaction_status": "purchased",
  "trolley_contents": {
    "bundle": [
      {
        "bundle_order_count": 1,
        "bundle_source_code": "ext_test0",
        "bundle_source_desc": "External Test Backend 0",
        "bundle_total_cost": 62.5,
        "bundle_total_seatprice": 51,
        "bundle_total_send_cost": 1.5,
        "bundle_total_surcharge": 10,
        "currency_code": "gbp",
        "order": [
          {
            "backend_purchase_reference": "PURCHASE-6710-1",
            "event": {
              "city_code": "london-uk",
              "city_desc": "London",
              "classes": {
                "dance": "Ballet & Dance"
              },
              "country_code": "uk",
              "country_desc": "United Kingdom",
              "critic_review_percent": 100,
              "custom_filter": [],
              "event_desc": "Matthew Bourne's Nutcracker TEST",
              "event_id": "6IF",
              "event_path": "/6IF-matthew-bourne-s-nutcracker-test/",
              "event_status": "live",
              "event_type": "simple_ticket",
              "event_upsell_list": {
                "event_id": [
                  "6IE",
                  "MH0"
                ]
              },
              "event_uri_desc": "Matthew-Bourne%27s-Nutcracker-TEST",
              "geo_data": {
                "latitude": 51.52961137,
                "longitude": -0.10601562
              },
              "has_no_perfs": false,
              "is_seated": true,
              "max_running_time": 120,
              "min_running_time": 120,
              "need_departure_date": false,
              "need_duration": false,
              "need_performance": true,
              "postcode": "EC1R 4TN",
              "show_perf_time": true,
              "source_code": "ext_test0",
              "source_desc": "External Test Backend 0",
              "user_review_percent": 100,
              "venue_desc": "Sadler's Wells",
              "venue_uri_desc": "Sadler%27s-Wells"
            },
            "got_requested_seats": false,
            "gross_commission": {
              "amount_excluding_vat": 7.13,
              "amount_including_vat": 8.55,
              "commission_currency_code": "gbp"
            },
            "item_number": 1,
            "performance": {
              "date_desc": "Tue, 13th June 2017",
              "event_id": "6IF",
              "has_pool_seats": true,
              "is_ghost": false,
              "is_limited": false,
              "iso8601_date_and_time": "2017-06-13T19:30:00+01:00",
              "perf_id": "6IF-B1S",
              "perf_name": "Including back stage pass",
              "running_time": 120,
              "time_desc": "7.30 PM"
            },
            "price_band_code": "C/pool",
            "send_method": {
              "send_code": "COBO",
              "send_cost": 1.5,
              "send_desc": "Collect from the venue",
              "send_final_type": "collect",
              "send_type": "collect"
            },
            "ticket_orders": {
              "ticket_order": [
                {
                  "discount_code": "ADULT",
                  "discount_desc": "Adult",
                  "no_of_seats": 1,
                  "sale_seatprice": 25,
                  "sale_surcharge": 4,
                  "seats": [
                    {
                      "col_id": "386",
                      "full_id": "NM386",
                      "is_restricted_view": false,
                      "row_id": "NM"
                    }
                  ],
                  "total_sale_seatprice": 25,
                  "total_sale_surcharge": 4
                },
                {
                  "discount_code": "CHILD",
                  "discount_desc": "Child rate",
                  "no_of_seats": 2,
                  "sale_seatprice": 13,
                  "sale_surcharge": 3,
                  "seats": [
                    {
                      "col_id": "383",
                      "full_id": "NM383",
                      "is_restricted_view": false,
                      "row_id": "NM"
                    },
                    {
                      "col_id": "380",
                      "full_id": "NM380",
                      "is_restricted_view": false,
                      "row_id": "NM"
                    }
                  ],
                  "total_sale_seatprice": 26,
                  "total_sale_surcharge": 6
                }
              ]
            },
            "ticket_type_code": "CIRCLE",
            "ticket_type_desc": "Upper circle",
            "total_no_of_seats": 3,
            "total_sale_seatprice": 51,
            "total_sale_surcharge": 10,
            "user_commission": {
              "amount_excluding_vat": 3.21,
              "amount_including_vat": 3.85,
              "commission_currency_code": "gbp"
            }
          }
        ],
        "purchase_result": {
          "is_semi_credit": false,
          "success": true
        }
      }
    ],
    "purchase_result": {
      "is_partial": false,
      "success": true
    },
    "transaction_id": "T000-0000-8RGW-3619",
    "transaction_uuid": "61cfd4eb-1f5b-11e7-b228-0025903268dc",
    "trolley_bundle_count": 1,
    "trolley_order_count": 1
  }
}
from pyticketswitch.send_method import SendMethod
from pyticketswitch.purchase_result import PurchaseResult
from pyticketswitch.seat import Seat
from pyticketswitch.event import Event
from pyticketswitch.status import Status
from pyticketswitch.customer import Customer
from pyticketswitch.bundle import Bundle
from pyticketswitch.performance import Performance
from pyticketswitch.order import TicketOrder
from pyticketswitch.trolley import Trolley
from pyticketswitch.order import Order

# An on credit purchase should always return a status object and will never
# return a callout.
Status(
    status='purchased',
    reserved_at=datetime.datetime(2017, 5, 3, 15, 1, 45, tzinfo=tzutc()),
    purchased_at=datetime.datetime(2017, 5, 3, 15, 14, 5, tzinfo=tzutc()),
    trolley=Trolley(
        transaction_uuid='6d080a78-3011-11e7-b228-0025903268dc',
        transaction_id='T000-0000-8ZVV-2E78',
        bundles=[
            Bundle(
                source_code='ext_test1',
                orders=[
                    Order(
                        item=1,
                        event=Event(
                            id='7AB',
                            status='live',
                            description='The Unremarkable Incident of the Cat at Lunchtime',
                            source='External Test Backend 1',
                            source_code='ext_test1',
                            event_type='simple_ticket',
                            venue='Lyric Apollo',
                            classes={
                                'theatre': 'Theatre'
                            },
                            postcode='W6 7ES',
                            city='London',
                            city_code='london-uk',
                            country='United Kingdom',
                            country_code='uk',
                            latitude=51.49306,
                            longitude=-0.22639,
                            max_running_time=90,
                            min_running_time=90,
                            show_performance_time=True,
                            has_performances=True,
                            is_seated=True,
                            needs_departure_date=False,
                            needs_duration=False,
                            needs_performance=False,
                        ),
                        performance=Performance(
                            id='7AB-5',
                            event_id='7AB',
                            date_time=datetime.datetime(2019, 1, 1, 15, 30, tzinfo=tzutc()) ,
                            date_description='Tue, 1st January 2019',
                            time_description='3.30 PM',
                            has_pool_seats=True,
                            is_limited=False,
                            is_ghost=False,
                            running_time=90,
                        ),
                        price_band_code='A/pool',
                        ticket_type_code='STALLS',
                        ticket_type_description='Stalls',
                        ticket_orders=[
                            TicketOrder(
                                code='NORMAL',
                                seats=[
                                    Seat(
                                        id='A1',
                                        column='1',
                                        row='A',
                                        separator='',
                                        is_restricted=True,
                                        seat_text='Restricted View',
                                    ),
                                    Seat(
                                        id='A2',
                                        column='2',
                                        row='A',
                                        separator='',
                                        is_restricted=True,
                                        seat_text='Restricted View',
                                    )
                                ],
                                description='Regular Ticket',
                                number_of_seats=2,
                                seatprice=50.0,
                                surcharge=5.0,
                                total_seatprice=100.0,
                                total_surcharge=10.0,
                            )
                        ],
                        number_of_seats=2,
                        total_seatprice=100.0,
                        total_surcharge=10.0,
                        seat_request_status='got_all',
                        requested_seat_ids=[
                            'A1',
                            'A2'
                        ],
                        backend_purchase_reference='PURCHASE-DA6E-0',
                        send_method=SendMethod(
                            code='VOUCH',
                            cost=0.0,
                            description='Printable eTicket',
                            type='selfprint',
                            can_generate_self_print=False,
                            self_print_voucher_url='https://api.ticketswitch.com/tickets/web_self_print.buy/demo?crypto_block=M_--R-aJRIR74rjx8gM2szdo9BEJZ8oV6wfGukxyZGDA2_DU2K3w-Y8L_3LWvIgKO_QxwMN8WmasaUuL_WpzKS-q2roXIWxXqjTxyDYZdge-wjDI0RZ8NpBAS0--Y',
                        ),
                    )
                ],
                description='External Test Backend 1',
                total_seatprice=100.0,
                total_surcharge=10.0,
                total_send_cost=0.0,
                total=110.0,
                currency_code='gbp',
            )
        ],
        purchase_result=PurchaseResult(
            success=True,
        ),
    ),
    languages=[
        'en'
    ],
    customer=Customer(
        first_name='Test',
        first_name_latin='Test',
        last_name='Tester',
        last_name_latin='Tester',
        address_lines=[
            'Metro Building',
            '1 Butterwick'
        ],
        address_lines_latin=[
            'Metro Building',
            '1 Butterwick'
        ],
        title='',
        title_latin='',
        initials='',
        initials_latin='',
        suffix='',
        suffix_latin='',
        country_code='uk',
        post_code='W6 8DL',
        post_code_latin='W6 8DL',
        town='London',
        town_latin='London',
        county='London',
        county_latin='London',
        country='United Kingdom',
        country_latin='United Kingdom',
        email='',
        home_phone='0203 137 7420',
        work_phone='0203 137 7420',
        agent_reference='',
        supplier_can_use_data=False,
        user_can_use_data=True,
        world_can_use_data=False,
    ),
)

The returned attributes are identical to the original purchase response, even if the purchase has since been cancelled, this response will still be the same verbatim copy of the original purchase call.

Attribute Description
customer The customer object, the customer attributes are as described in the purchase response.
language_list Not useful for most partners, can be ignored.
purchase_iso8601_date_and_time The purchase time in ISO 8601 format.
reserve_iso8601_date_and_time The reserve time in ISO 8601 format.
transaction_status This will be the original status that was reported at purchase, time (i.e. purchased, failed or attempting) and it will not change because this is a verbatim copy of the original purchase call.
trolley_contents The trolley object, the trolley attributes are as described in the purchase response.

Status

Definition

GET https://api.ticketswitch.com/f13/status.v1?transaction_uuid={trans_uuid}

This resource allows you to view the details and status of a transaction. A transaction is created when tickets are reserved, and it changes status if it is purchased or released. Status can be called on transactions in any state. As the status call is a blocking call, only call the status if you require an up to date status, if you simply want the result of the reserve or purchase you just made then please use the Reserve Page Archive or Purchase Page Archive API calls.

Note that transactions that have been cancelled still have a transaction_status of purchased — you must check the cancellation_status at the order level to know if a transaction (or orders within) have been cancelled. See the cancel docs for more information on this point.

Request

Example request

curl https://api.ticketswitch.com/f13/status.v1 \
    -u "demo:demopass" \
    -d "transaction_uuid=284d9c3a-d698-11e6-be8c-002590326962" \
    --compressed \
    -G
from pyticketswitch import Client

client = Client('demo', 'demopass')
status, meta = client.get_status(transaction_uuid='6d080a78-3011-11e7-b228-0025903268dc')
Parameter Description
add_customer Retrieve customer data (only applies to purchased transactions)
add_external_sale_page Retrieve the HTML for the confirmation page, if you requested Ingresso to save this when purchasing (only applies to purchased transactions). Primarily for internal use.
transaction_uuid The unique identifier returned by a previous reserve.

Response

Example response

{
  "language_list": "en-gb,en,en-us,nl",
  "minutes_left_on_reserve": 14.3,
  "moneyflow_channel_code": "demo",
  "remote_site": "",
  "reserve_iso8601_date_and_time": "2017-01-09T18:19:27Z",
  "reserve_user": {
    "backend_group": "demo_internal_credit_group",
    "content_group": "",
    "default_country_code": "uk",
    "is_b2b": true,
    "real_name": "Demonstration User",
    "statement_descriptor": "",
    "style": "fixed-tabs",
    "sub_style": "styled-aff-default",
    "sub_sub_style": "ingresso-generic",
    "sub_user": "",
    "user_id": "demo"
  },
  "transaction_status": "reserved",
  "trolley": {
    "bundle": [
      {
        "bundle_order_count": 1,
        "bundle_source_code": "ext_test0",
        "bundle_source_desc": "External Test Backend 0",
        "bundle_total_cost": 71.5,
        "bundle_total_seatprice": 70,
        "bundle_total_send_cost": 1.5,
        "bundle_total_surcharge": 0,
        "currency": {
          "currency_code": "gbp"
        },
        "order": [
          {
            "event": {
              "city_code": "london-uk",
              "city_desc": "London",
              "classes": {
                "dance": "Ballet & Dance"
              },
              "country_code": "uk",
              "country_desc": "United Kingdom",
              "critic_review_percent": 100,
              "custom_filter": [],
              "event_desc": "Matthew Bourne's Nutcracker TEST",
              "event_id": "6IF",
              "event_path": "/6IF-matthew-bourne-s-nutcracker-test/",
              "event_status": "live",
              "event_type": "simple_ticket",
              "event_upsell_list": {
                "event_id": [
                  "6IE",
                  "MH0"
                ]
              },
              "event_uri_desc": "Matthew-Bourne%27s-Nutcracker-TEST",
              "geo_data": {
                "latitude": 51.52961137,
                "longitude": -0.10601562
              },
              "has_no_perfs": false,
              "is_seated": true,
              "max_running_time": 120,
              "min_running_time": 120,
              "need_departure_date": false,
              "need_duration": false,
              "need_performance": true,
              "postcode": "EC1R 4TN",
              "show_perf_time": true,
              "source_code": "ext_test0",
              "source_desc": "External Test Backend 0",
              "user_review_percent": 100,
              "venue_desc": "Sadler's Wells",
              "venue_uri_desc": "Sadler%27s-Wells"
            },
            "item_number": 1,
            "performance": {
              "date_desc": "Tue, 9th May 2017",
              "event_id": "6IF",
              "has_pool_seats": true,
              "is_ghost": false,
              "is_limited": false,
              "iso8601_date_and_time": "2017-05-09T19:30:00+01:00",
              "perf_id": "6IF-B0T",
              "perf_name": "Including back stage pass",
              "time_desc": "7.30 PM"
            },
            "price_band_code": "A/pool",
            "seat_request_status": "not_requested",
            "ticket_orders": {
              "ticket_order": [
                {
                  "discount_code": "",
                  "discount_desc": "",
                  "no_of_seats": 2,
                  "sale_seatprice": 35,
                  "sale_surcharge": 0,
                  "seats": [
                    {
                      "col_id": "144",
                      "full_id": "FN144",
                      "is_restricted_view": false,
                      "row_id": "FN"
                    },
                    {
                      "col_id": "143",
                      "full_id": "FN143",
                      "is_restricted_view": false,
                      "row_id": "FN"
                    }
                  ],
                  "total_sale_seatprice": 70,
                  "total_sale_surcharge": 0
                }
              ]
            },
            "ticket_type_code": "CIRCLE",
            "ticket_type_desc": "Upper circle",
            "total_no_of_seats": 2,
            "total_sale_seatprice": 70,
            "total_sale_surcharge": 0
          }
        ]
      }
    ],
    "minutes_left_on_reserve": 14.3,
    "transaction_uuid": "284d9c3a-d698-11e6-be8c-002590326962",
    "trolley_bundle_count": 1,
    "trolley_order_count": 1
  }
}
from pyticketswitch.country import Country
from pyticketswitch.trolley import Trolley
from pyticketswitch.status import Status
from pyticketswitch.seat import Seat
from pyticketswitch.performance import Performance
from pyticketswitch.order import TicketOrder
from pyticketswitch.event import Event
from pyticketswitch.send_method import SendMethod
from pyticketswitch.order import Order
from pyticketswitch.address import Address
from pyticketswitch.bundle import Bundle

Status(
    status='reserved',
    reserved_at=datetime.datetime(2017, 5, 3, 17, 2, 17, tzinfo=tzutc()),
    trolley=Trolley(
        transaction_uuid='43768b36-3022-11e7-979f-002590326962',
        bundles=[
            Bundle(
                source_code='ext_test0',
                orders=[
                    Order(
                        item=1,
                        event=Event(
                            id='6IF',
                            status='live',
                            description="Matthew Bourne's Nutcracker TEST",
                            source='External Test Backend 0',
                            source_code='ext_test0',
                            event_type='simple_ticket',
                            venue="Sadler's Wells",
                            classes={
                                'dance': 'Ballet & Dance'
                            },
                            filters=[

                            ],
                            postcode='EC1R 4TN',
                            city='London',
                            city_code='london-uk',
                            country='United Kingdom',
                            country_code='uk',
                            latitude=51.52961137,
                            longitude=-0.10601562,
                            max_running_time=120,
                            min_running_time=120,
                            show_performance_time=True,
                            has_performances=True,
                            is_seated=True,
                            needs_departure_date=False,
                            needs_duration=False,
                            needs_performance=False,
                            upsell_list=[
                                '6IE',
                                'MH0'
                            ],
                            critic_review_percent=100,
                        ),
                        performance=Performance(
                            id='6IF-B0O',
                            event_id='6IF',
                            date_time=datetime.datetime(2017, 5, 4, 19, 30, tzinfo=tzoffset(None, 3600)),
                            date_description='Thu, 4th May 2017',
                            time_description='7.30 PM',
                            has_pool_seats=True,
                            is_limited=False,
                            is_ghost=False,
                            running_time=120,
                        ),
                        price_band_code='A/pool',
                        ticket_type_code='STALLS',
                        ticket_type_description='Stalls',
                        ticket_orders=[
                            TicketOrder(
                                code='',
                                seats=[
                                    Seat(
                                        id='HJ401',
                                        column='401',
                                        row='HJ',
                                        separator='',
                                        is_restricted=False,
                                    ),
                                    Seat(
                                        id='HJ402',
                                        column='402',
                                        row='HJ',
                                        separator='',
                                        is_restricted=False,
                                    )
                                ],
                                description='',
                                number_of_seats=2,
                                seatprice=21.0,
                                surcharge=3.0,
                                total_seatprice=42.0,
                                total_surcharge=6.0,
                            )
                        ],
                        number_of_seats=2,
                        total_seatprice=42.0,
                        total_surcharge=6.0,
                        seat_request_status='not_requested',
                        requested_seat_ids=[

                        ],
                        send_method=SendMethod(
                            code='COBO',
                            cost=1.5,
                            description='Collect from the venue',
                            type='collect',
                        ),
                    )
                ],
                description='External Test Backend 0',
                total_seatprice=42.0,
                total_surcharge=6.0,
                total_send_cost=1.5,
                total=49.5,
                currency_code='gbp',
            )
        ],
        discarded_orders=[

        ],
        minutes_left=14.5,
    ),
    languages=[
        'en'
    ],
    needs_payment_card=False,
    needs_email_address=False,
    needs_agent_reference=False,
    can_edit_address=True,
    allowed_countries=[
        Country(
            code='uk',
            description='United Kingdom',
        )
    ],
    minutes_left=14.5,
)

The returned attributes are dependent on the status of the transaction. For example a purchased transaction will appear differently to a released transaction.

Attribute Description
customer Detail of the purchasing customer; only included when the add_customer parameter is present and the transaction_status is purchased. The fields returned are as described in purchase.
external_sale_page The detail of the confirmation page that was displayed to customers. Only included when the add_external_sale_page parameter is present and the transaction_status is purchased.
purchase_iso8601_date_and_time The time the tickets were successfully purchased.
reserve_iso8601_date_and_time The time the tickets were successfully reserved.
transaction_status One of reserved, released, purchased, failed, or attempting (will only be seen if the customer is being redirected to a payment page - most partners will not see this).
trolley The trolley object. If the transaction_status is reserved or released, the trolley attributes are as described in the reserve response. If the transaction_status is purchased the trolley attributes are as described in the purchase response. Note that if the transaction_status is released you should ignore the value of minutes_left_on_reserve.

Trans ID Status

Definition

GET https://api.ticketswitch.com/f13/trans_id_status.v1?transaction_id={trans_id}

This resource is to provide legacy API support. In the old XML API after reserving tickets a transaction ID was returned. This has been replaced with a transaction UUID. If you have made purchases using the old XML API and you need to retrieve details of the transaction then you can use trans_id_status lets you request status for a particular transaction_id. If you have only used this JSON API then there is no need to use trans_id_status.

Request

Example request

curl https://api.ticketswitch.com/f13/trans_id_status.v1 \
    -u "demo:demopass" \
    -d "transaction_id=T000-0000-8LZT-WA8D" \
    --compressed \
    -G
from pyticketswitch import Client

client = Client('demo', 'demopass')
status, meta = client.get_status(transaction_id='T000-0000-8ZVV-2E78')

Parameter Description
add_customer Retrieve customer data (only applies to purchased transactions)
add_external_sale_page Retrieve the HTML for the confirmation page, if you requested Ingresso to save this when purchasing (only applies to purchased transactions). Primarily for internal use.
transaction_id The unique identifier returned by a previous reserve.

Response

Example response

{
  "currency_details": {
    "gbp": {
      "currency_code": "gbp",
      "currency_factor": 100,
      "currency_number": 826,
      "currency_places": 2,
      "currency_post_symbol": "",
      "currency_pre_symbol": "£"
    }
  },
  "language_list": [
    "en"
  ],
  "purchase_iso8601_date_and_time": "2017-02-20T19:42:55Z",
  "reserve_iso8601_date_and_time": "2017-02-20T19:42:55Z",
  "transaction_status": "purchased",
  "trolley_contents": {
    "bundle": [
      {
        "bundle_order_count": 1,
        "bundle_source_code": "ext_test0",
        "bundle_source_desc": "External Test Backend 0",
        "bundle_total_cost": 71.5,
        "bundle_total_seatprice": 70,
        "bundle_total_send_cost": 1.5,
        "bundle_total_surcharge": 0,
        "currency_code": "gbp",
        "order": [
          {
            "backend_purchase_reference": "PURCHASE-1445-1",
            "event": {
              "city_code": "london-uk",
              "city_desc": "London",
              "classes": {
                "dance": "Ballet & Dance"
              },
              "country_code": "uk",
              "country_desc": "United Kingdom",
              "critic_review_percent": 100,
              "custom_filter": [],
              "event_desc": "Matthew Bourne's Nutcracker TEST",
              "event_id": "6IF",
              "event_path": "/6IF-matthew-bourne-s-nutcracker-test/",
              "event_status": "live",
              "event_type": "simple_ticket",
              "event_upsell_list": {
                "event_id": [
                  "6IE",
                  "MH0"
                ]
              },
              "event_uri_desc": "Matthew-Bourne%27s-Nutcracker-TEST",
              "geo_data": {
                "latitude": 51.52961137,
                "longitude": -0.10601562
              },
              "has_no_perfs": false,
              "is_seated": true,
              "max_running_time": 120,
              "min_running_time": 120,
              "need_departure_date": false,
              "need_duration": false,
              "need_performance": true,
              "postcode": "EC1R 4TN",
              "show_perf_time": true,
              "source_code": "ext_test0",
              "source_desc": "External Test Backend 0",
              "user_review_percent": 100,
              "venue_desc": "Sadler's Wells",
              "venue_uri_desc": "Sadler%27s-Wells"
            },
            "got_requested_seats": false,
            "gross_commission": {
              "amount_excluding_vat": 0.25,
              "amount_including_vat": 0.3,
              "commission_currency_code": "gbp"
            },
            "item_number": 1,
            "performance": {
              "date_desc": "Thu, 23rd February 2017",
              "event_id": "6IF",
              "has_pool_seats": true,
              "is_ghost": false,
              "is_limited": false,
              "iso8601_date_and_time": "2017-02-23T19:30:00Z",
              "perf_id": "6IF-A8Q",
              "running_time": 120,
              "time_desc": "7.30 PM"
            },
            "price_band_code": "A/pool",
            "send_method": {
              "send_code": "COBO",
              "send_cost": 1.5,
              "send_desc": "Collect from the venue",
              "send_final_type": "collect",
              "send_type": "collect"
            },
            "ticket_orders": {
              "ticket_order": [
                {
                  "discount_code": "ADULT",
                  "discount_desc": "Adult",
                  "no_of_seats": 2,
                  "sale_seatprice": 35,
                  "sale_surcharge": 0,
                  "seats": [
                    {
                      "col_id": "140",
                      "full_id": "SQ140",
                      "is_restricted_view": false,
                      "row_id": "SQ"
                    },
                    {
                      "col_id": "139",
                      "full_id": "SQ139",
                      "is_restricted_view": false,
                      "row_id": "SQ"
                    }
                  ],
                  "total_sale_seatprice": 70,
                  "total_sale_surcharge": 0
                }
              ]
            },
            "ticket_type_code": "CIRCLE",
            "ticket_type_desc": "Upper circle",
            "total_no_of_seats": 2,
            "total_sale_seatprice": 70,
            "total_sale_surcharge": 0,
            "user_commission": {
              "amount_excluding_vat": 0.11,
              "amount_including_vat": 0.14,
              "commission_currency_code": "gbp"
            }
          }
        ],
        "purchase_result": {
          "is_semi_credit": false,
          "success": true
        }
      }
    ],
    "purchase_result": {
      "is_partial": false,
      "success": true
    },
    "transaction_id": "T000-0000-8LZT-WA8D",
    "transaction_uuid": "c6335e88-f7a4-11e6-b286-0025903268dc",
    "trolley_bundle_count": 1,
    "trolley_order_count": 1
  }
}

from pyticketswitch.trolley import Trolley
from pyticketswitch.status import Status
from pyticketswitch.seat import Seat
from pyticketswitch.performance import Performance
from pyticketswitch.order import TicketOrder
from pyticketswitch.purchase_result import PurchaseResult
from pyticketswitch.event import Event
from pyticketswitch.send_method import SendMethod
from pyticketswitch.order import Order
from pyticketswitch.bundle import Bundle

Status(
    status='purchased',
    reserved_at=datetime.datetime(2017, 5, 3, 15, 1, 45, tzinfo=tzutc()),
    purchased_at=datetime.datetime(2017, 5, 3, 15, 14, 5, tzinfo=tzutc()),
    trolley=Trolley(
        transaction_uuid='6d080a78-3011-11e7-b228-0025903268dc',
        transaction_id='T000-0000-8ZVV-2E78',
        bundles=[
            Bundle(
                source_code='ext_test1',
                orders=[
                    Order(
                        item=1,
                        event=Event(
                            id='7AB',
                            status='live',
                            description='The Unremarkable Incident of the Cat at Lunchtime',
                            source='External Test Backend 1',
                            source_code='ext_test1',
                            event_type='simple_ticket',
                            venue='Lyric Apollo',
                            classes={
                                'theatre': 'Theatre'
                            },
                            postcode='W6 7ES',
                            city='London',
                            city_code='london-uk',
                            country='United Kingdom',
                            country_code='uk',
                            latitude=51.49306,
                            longitude=-0.22639,
                            max_running_time=90,
                            min_running_time=90,
                            show_performance_time=True,
                            has_performances=True,
                            is_seated=True,
                            needs_departure_date=False,
                            needs_duration=False,
                            needs_performance=False,
                        ),
                        performance=Performance(
                            id='7AB-5',
                            event_id='7AB',
                            date_time=datetime.datetime(2019, 1, 1, 15, 30, tzinfo=tzutc()),
                            date_description='Tue, 1st January 2019',
                            time_description='3.30 PM',
                            has_pool_seats=True,
                            is_limited=False,
                            is_ghost=False,
                            running_time=90,
                        ),
                        price_band_code='A/pool',
                        ticket_type_code='STALLS',
                        ticket_type_description='Stalls',
                        ticket_orders=[
                            TicketOrder(
                                code='NORMAL',
                                seats=[
                                    Seat(
                                        id='A1',
                                        column='1',
                                        row='A',
                                        separator='',
                                        is_restricted=True,
                                        seat_text='Restricted View',
                                    ),
                                    Seat(
                                        id='A2',
                                        column='2',
                                        row='A',
                                        separator='',
                                        is_restricted=True,
                                        seat_text='Restricted View',
                                    )
                                ],
                                description='Regular Ticket',
                                number_of_seats=2,
                                seatprice=50.0,
                                surcharge=5.0,
                                total_seatprice=100.0,
                                total_surcharge=10.0,
                            )
                        ],
                        number_of_seats=2,
                        total_seatprice=100.0,
                        total_surcharge=10.0,
                        seat_request_status='got_all',
                        requested_seat_ids=[
                            'A1',
                            'A2'
                        ],
                        backend_purchase_reference='PURCHASE-DA6E-0',
                        send_method=SendMethod(
                            code='VOUCH',
                            cost=0.0,
                            description='Printable eTicket',
                            type='selfprint',
                            can_generate_self_print=False,
                            self_print_voucher_url='https://api.ticketswitch.com/tickets/web_self_print.buy/demo?crypto_block=U_--z_v1JesEuC-2FgKkj4LEhJdbZVhIdnBp3b0sP0uh1KqsYF_fumHhC_IFKIXh471k1Del_9Wi0W8_8Ay7xJNhbK299MEf-wLwbOmtNBdnzh8BZ9icsINHBS0w5gNCc7zbY',
                        ),
                    )
                ],
                description='External Test Backend 1',
                total_seatprice=100.0,
                total_surcharge=10.0,
                total_send_cost=0.0,
                total=110.0,
                currency_code='gbp',
            )
        ],
        purchase_result=PurchaseResult(
            success=True,
        ),
    ),
    languages=[
        'en'
    ],
)

The returned attributes are dependent on the status of the transaction. For example a purchased transaction will appear differently to a released transaction.

Attribute Description
customer Detail of the purchasing customer; only included when the add_customer parameter is present and the transaction_status is purchased. The fields returned are as described in purchase.
external_sale_page The detail of the confirmation page that was displayed to customers. Only included when the add_external_sale_page parameter is present and the transaction_status is purchased.
purchase_iso8601_date_and_time The time the tickets were successfully purchased.
reserve_iso8601_date_and_time The time the tickets were successfully reserved.
transaction_status One of reserved, released, purchased, failed, or attempting (will only be seen if the customer is being redirected to a payment page - most partners will not see this).
trolley The trolley object. If the transaction_status is reserved or released, the trolley attributes are as described in the reserve response. If the transaction_status is purchased the trolley attributes are as described in the purchase response. Note that if the transaction_status is released you should ignore the value of minutes_left_on_reserve.

Cancel

Definition

POST https://api.ticketswitch.com/f13/cancel.v1?transaction_uuid={trans_uuid}&cancel_items_list=1,2

This endpoint allows users to attempt to cancel purchased transactions (there is no guarantee that cancellations will succeed). By default, users are unable to cancel transactions. If you believe that you should be able to cancel transactions then contact us

If you would like to attempt to cancel a transaction, follow these steps: 1. Check if the order items within the transaction are cancellable by looking at the cancellation_status of each of the order items in the purchase or status response (they are cancellable if cancellation_status is possible). 2. Attempt the cancellation of the "cancellation_status": "possible" order items. You can specify which order items to cancel in the transaction with the optional list, cancel_items_list. If you don’t specify any order items to cancel then it will be assumed that the whole transaction should be cancelled (Ingresso will then attempt to cancel all items that can be cancelled). 3. Check the response to see if the cancellation worked as you expected, for example some order items may not succeed in getting cancelled, whereas others might. Cancelling some items may cause other items to be cancelled. Check both the high level cancelled_item_numbers and the updated cancellation_status on each of the orders within the trolley. There might be a charge for the cancellation.

Request

Example request - cancel entire transaction

curl https://api.ticketswitch.com/f13/cancel.v1 \
    -u "demo:demopass" \
    -d "transaction_uuid=284d9c3a-d698-11e6-be8c-002590326962" \
    --compressed \
    -G
from pyticketswitch import Client

client = Client('demo', 'demopass')
status, meta = client.cancel_purchase(transaction_uuid='284d9c3a-d698-11e6-be8c-002590326962')

Example request - specify order items to cancel by item number

curl https://api.ticketswitch.com/f13/cancel.v1 \
    -u "demo:demopass" \
    -d "transaction_uuid=284d9c3a-d698-11e6-be8c-002590326962" \
    -d "cancel_items_list=1,3" \
    --compressed \
    -G
from pyticketswitch import Client

client = Client('demo', 'demopass')
status, meta = client.cancel_purchase(transaction_uuid='284d9c3a-d698-11e6-be8c-002590326962', cancel_items_list=[1,3])
Parameter Description
transaction_uuid The unique identifier returned by a previous purchase.
cancel_items_list An optional parameter that may be included in the request. It is a list of items to cancel in the transaction (note that cancelling some items may cause other items to be cancelled as well).

Response

Example response – successful cancellation

{
   "trolley_contents" : {
      "trolley_bundle_count" : 1,
      "trolley_order_count" : 1,
      "bundle" : [
         {
            "bundle_total_seatprice" : 32,
            "bundle_total_send_cost" : 1.5,
            "order" : [
               {
                  "price_band_code" : "A/pool",
                  "internal_reserve_sub_ref2" : "NUT SUB 2",
                  "backend_cancellation_reference" : "ATTEMPT-482281",
                  "total_sale_surcharge" : 5,
                  "item_number" : 1,
                  "performance" : {
                     "running_time" : 120,
                     "has_pool_seats" : true,
                     "event_id" : "6IF",
                     "time_desc" : "7.30 PM",
                     "is_limited" : false,
                     "perf_id" : "6IF-D9P",
                     "is_ghost" : false,
                     "iso8601_date_and_time" : "2019-04-26T19:30:00+01:00",
                     "date_desc" : "Fri, 26th April 2019"
                  },
                  "backend_purchase_reference" : "PURCHASE-286D",
                  "user_commission" : {
                     "amount_including_vat" : 11.4,
                     "commission_currency_code" : "gbp",
                     "amount_excluding_vat" : 9.5
                  },
                  "send_method" : {
                     "send_cost" : 1.5,
                     "send_desc" : "Collect from venue",
                     "send_final_comment" : "Instructions for collecting tickets at the venue box office:\n- Tickets must be collected by the cardholder with valid photo identification and the payment card.\n- The cardholder’s signature will be required on receipt of these tickets.\n- Tickets are only available for collection on the day of the performance.\n- Guests are advised to arrive at least 30 minutes before the performance time.\n- If the cardholder is unable to collect these tickets please contact Guest Services on 0800 640 8101.\n\nCan we help?\nIf you require further information please contact our Guest Services team:\nLive chat or call 0800 640 8101 (Monday – Sunday, 9am – 9pm GMT/BST)",
                     "send_type" : "collect",
                     "send_code" : "COBO",
                     "send_final_type" : "collect"
                  },
                  "ticket_type_desc" : "Stalls",
                  "gross_commission" : {
                     "amount_including_vat" : 11.4,
                     "amount_excluding_vat" : 9.5,
                     "commission_currency_code" : "gbp"
                  },
                  "cancellation_status" : "cancelled",
                  "ticket_orders" : {
                     "ticket_order" : [
                        {
                           "total_sale_seatprice" : 21,
                           "sale_surcharge" : 3,
                           "total_sale_combined" : 24,
                           "sale_seatprice" : 21,
                           "seats" : [
                              {
                                 "full_id" : "YG167",
                                 "is_restricted_view" : false,
                                 "col_id" : "167",
                                 "row_id" : "YG"
                              }
                           ],
                           "discount_code" : "ADULT",
                           "discount_desc" : "Adult standard",
                           "sale_combined" : 24,
                           "total_sale_surcharge" : 3,
                           "no_of_seats" : 1
                        },
                        {
                           "total_sale_surcharge" : 2,
                           "sale_combined" : 13,
                           "discount_desc" : "Adult 18+ including behind the scenes tour",
                           "discount_code" : "CHILD",
                           "no_of_seats" : 1,
                           "sale_surcharge" : 2,
                           "total_sale_seatprice" : 11,
                           "seats" : [
                              {
                                 "row_id" : "YG",
                                 "col_id" : "168",
                                 "is_restricted_view" : false,
                                 "full_id" : "YG168"
                              }
                           ],
                           "sale_seatprice" : 11,
                           "total_sale_combined" : 13
                        }
                     ]
                  },
                  "cancellation_comment" : "",
                  "total_sale_combined" : 37,
                  "total_no_of_seats" : 2,
                  "price_band_desc" : "Top price (band A)",
                  "seat_request_status" : "not_requested",
                  "ticket_type_code" : "STALLS",
                  "total_sale_seatprice" : 32,
                  "event" : {
                     "has_no_perfs" : false,
                     "min_running_time" : 120,
                     "need_departure_date" : false,
                     "need_duration" : false,
                     "city_code" : "london-uk",
                     "show_perf_time" : true,
                     "is_seated" : true,
                     "event_uri_desc" : "Matthew-Bourne%27s-Nutcracker%21",
                     "source_code" : "ext_test0",
                     "source_desc" : "Test SystemZero for on-credit backend group",
                     "event_desc" : "Matthew Bourne's Nutcracker!",
                     "event_type" : "simple_ticket",
                     "event_status" : "live",
                     "event_upsell_list" : {
                        "event_id" : [
                           "6IE",
                           "6KU"
                        ]
                     },
                     "venue_uri_desc" : "Sadler%27s-Wells",
                     "critic_review_percent" : 80,
                     "country_desc" : "United Kingdom",
                     "venue_desc" : "Sadler's Wells",
                     "max_running_time" : 120,
                     "geo_data" : {
                        "latitude" : 51.5,
                        "longitude" : -0.15
                     },
                     "event_id" : "6IF",
                     "need_performance" : true,
                     "postcode" : "EC1R 4TN",
                     "city_desc" : "London",
                     "is_add_on" : false,
                     "country_code" : "uk",
                     "classes" : {
                        "theatre" : "Theatre"
                     },
                     "is_auto_quantity_add_on" : false,
                     "custom_filter" : []
                  },
                  "internal_reserve_sub_ref" : "NUT SUB 1",
                  "requested_seat_ids" : [],
                  "internal_purchase_sub_ref" : "SUBREF-1:NUT SUB 2:NUT SUB 1"
               }
            ],
            "purchase_result" : {
               "can_cancel_individual_orders" : false,
               "success" : true,
               "backend_purchase_reference" : "PURCHASE-286D",
               "is_semi_credit" : false
            },
            "bundle_total_surcharge" : 5,
            "bundle_order_count" : 1,
            "bundle_source_code" : "ext_test0",
            "bundle_total_cost" : 38.5,
            "bundle_source_desc" : "Test SystemZero for on-credit backend group",
            "currency_code" : "gbp"
         }
      ],
      "transaction_uuid" : "284d9c3a-d698-11e6-be8c-002590326962",
      "purchase_result" : {
         "success" : true,
         "is_partial" : false
      },
      "transaction_id" : "U000-0000-2M96-DEVX"
   },
   "currency_details" : {
      "gbp" : {
         "currency_pre_symbol" : "£",
         "currency_post_symbol" : "",
         "currency_factor" : 100,
         "currency_code" : "gbp",
         "currency_number" : 826,
         "currency_places" : 2
      }
   },
   "cancelled_item_numbers" : [
      1
   ]
}
from pyticketswitch.trolley import Trolley
from pyticketswitch.cancellation import CancellationResult
from pyticketswitch.seat import Seat
from pyticketswitch.performance import Performance
from pyticketswitch.purchase_result import PurchaseResult
from pyticketswitch.order import TicketOrder
from pyticketswitch.event import Event
from pyticketswitch.send_method import SendMethod
from pyticketswitch.order import Order
from pyticketswitch.bundle import Bundle

CancellationResult(
    cancelled_item_numbers=[1],
    trolley=Trolley(
        transaction_uuid='284d9c3a-d698-11e6-be8c-002590326962',
        bundles=[
            Bundle(
                source_code='ext_test0',
                orders=[
                    Order(
                        item=1,
                        backend_cancellation_reference='ATTEMPT-482281',
                        backend_purchase_reference='PURCHASE-286D',
                        cancellation_comment='',
                        cancellation_status='cancelled',
                        event=Event(
                            id='6IF',
                            status='live',
                            description="Matthew Bourne's Nutcracker TEST",
                            source='External Test Backend 0',
                            source_code='ext_test0',
                            event_type='simple_ticket',
                            venue="Sadler's Wells",
                            classes={
                                'dance': 'Ballet & Dance'
                            },
                            postcode='EC1R 4TN',
                            city='London',
                            city_code='london-uk',
                            country='United Kingdom',
                            country_code='uk',
                            latitude=51.52961137,
                            longitude=-0.10601562,
                            max_running_time=120,
                            min_running_time=120,
                            show_performance_time=True,
                            has_performances=True,
                            is_seated=True,
                            needs_departure_date=False,
                            needs_duration=False,
                            needs_performance=False,
                            upsell_list=[
                                '6IE',
                                'MH0'
                            ],
                            critic_review_percent=100,
                        ),
                        performance=Performance(
                            id='6IF-D9P',
                            event_id='6IF',
                            date_time=datetime.datetime(2019, 4, 26, 19, 30, tzinfo=tzoffset(None, 3600)),
                            date_description='Fri, 26th April 2019',
                            time_description='7.30 PM',
                            has_pool_seats=True,
                            is_limited=False,
                            is_ghost=False,
                            running_time=120,
                        ),
                        price_band_code='A/pool',
                        ticket_type_code='STALLS',
                        ticket_type_description='Stalls',
                        ticket_orders=[
                            TicketOrder(
                                code='',
                                seats=[
                                    Seat(
                                        id='YG167',
                                        column='167',
                                        row='YG',
                                        separator='',
                                        is_restricted=False,
                                    ),
                                ],
                                description='',
                                number_of_seats=1,
                                seatprice=21.0,
                                surcharge=3.0,
                                total_seatprice=21.0,
                                total_surcharge=3.0,
                            ),
                            TicketOrder(
                                code='',
                                seats=[
                                    Seat(
                                        id='YG168',
                                        column='168',
                                        row='YG',
                                        separator='',
                                        is_restricted=False,
                                    ),
                                ],
                                description='',
                                number_of_seats=1,
                                seatprice=11.0,
                                surcharge=2.0,
                                total_seatprice=11.0,
                                total_surcharge=2.0,
                            )
                        ],
                        number_of_seats=2,
                        total_seatprice=32.0,
                        total_surcharge=5.0,
                        seat_request_status='not_requested',
                        send_method=SendMethod(
                            code='COBO',
                            cost=1.5,
                            description='Collect from the venue',
                            type='collect',
                        ),
                    )
                ],
                description='External Test Backend 0',
                total_seatprice=32.0,
                total_surcharge=5.0,
                total_send_cost=1.5,
                total=38.5,
                currency_code='gbp',
                purchase_result=PurchaseResult(
                    success=True,
                    can_cancel_individual_orders=False,
                    backend_purchase_reference="PURCHASE-286D",
                    is_semi_credit=False
                ),
            )
        ],
        purchase_result=PurchaseResult(
            success=True,
            is_partial=False,
        ),
    ),
)

Example response – must also cancel

{
   "must_also_cancel" : [
      {
         "cancellation_comment" : "",
         "send_method" : {
            "send_cost_in_desired" : 8.76,
            "send_type" : "post",
            "send_final_type" : "post",
            "send_desc" : "Post worldwide",
            "send_cost" : 10,
            "send_code" : "POST"
         },
         "ticket_orders" : {
            "ticket_order" : [
               {
                  "seats" : [
                     {
                        "is_restricted_view" : false,
                        "row_id" : "YC",
                        "full_id" : "YC472",
                        "col_id" : "472"
                     },
                     {
                        "full_id" : "YC473",
                        "col_id" : "473",
                        "row_id" : "YC",
                        "is_restricted_view" : false
                     },
                     {
                        "col_id" : "474",
                        "full_id" : "YC474",
                        "row_id" : "YC",
                        "is_restricted_view" : false
                     }
                  ],
                  "sale_combined_in_desired" : 135.75,
                  "sale_surcharge_in_desired" : 13.14,
                  "sale_seatprice" : 140,
                  "total_sale_surcharge" : 45,
                  "total_sale_combined" : 465,
                  "discount_desc" : "",
                  "total_sale_combined_in_desired" : 407.24,
                  "sale_surcharge" : 15,
                  "total_sale_surcharge_in_desired" : 39.41,
                  "no_of_seats" : 3,
                  "total_sale_seatprice" : 420,
                  "sale_combined" : 155,
                  "sale_seatprice_in_desired" : 122.61,
                  "total_sale_seatprice_in_desired" : 367.83,
                  "discount_code" : ""
               }
            ]
         },
         "total_sale_combined_in_desired" : 407.24,
         "total_sale_seatprice" : 420,
         "seat_request_status" : "not_requested",
         "backend_cancellation_reference" : "",
         "requested_seat_ids" : [],
         "internal_purchase_sub_ref" : "",
         "ticket_type_desc" : "Menu French Cancan",
         "internal_reserve_sub_ref" : "",
         "price_band_code" : "A/pool",
         "user_commission" : {
            "commission_currency_code" : "eur",
            "amount_including_vat" : 0,
            "amount_excluding_vat" : 0
         },
         "total_sale_combined" : 465,
         "backend_purchase_reference" : "PURCHASE-3AFD",
         "event" : {
            "custom_filter" : [],
            "min_running_time" : 120,
            "geo_data" : {
               "latitude" : 0,
               "longitude" : 0
            },
            "postcode" : "75018",
            "event_id" : "BPT",
            "venue_uri_desc" : "Bal-du-Moulin-Rouge",
            "has_no_perfs" : false,
            "need_performance" : true,
            "source_code" : "ext_test1",
            "event_uri_desc" : "Moulin-Rouge-%28Dinner-Show%29",
            "event_type" : "simple_ticket",
            "is_auto_quantity_add_on" : false,
            "country_code" : "fr",
            "venue_desc" : "Bal du Moulin Rouge",
            "show_perf_time" : true,
            "classes" : {
               "attract" : "Attractions",
               "theatre" : "Theatre"
            },
            "source_desc" : "Test System One",
            "max_running_time" : 120,
            "event_status" : "live",
            "need_departure_date" : false,
            "need_duration" : false,
            "event_desc" : "Moulin Rouge (Dinner Show)",
            "country_desc" : "France",
            "is_seated" : true,
            "is_add_on" : false
         },
         "gross_commission" : {
            "amount_including_vat" : 60,
            "amount_excluding_vat" : 50,
            "commission_currency_code" : "eur"
         },
         "total_no_of_seats" : 3,
         "ticket_type_code" : "CANCAN",
         "performance" : {
            "is_limited" : false,
            "running_time" : 120,
            "iso8601_date_and_time" : "2019-04-01T19:00:00+02:00",
            "event_id" : "BPT",
            "perf_id" : "BPT-E6P",
            "date_desc" : "Mon, 1st April 2019",
            "has_pool_seats" : true,
            "is_ghost" : false,
            "time_desc" : "7.00 PM"
         },
         "total_sale_surcharge_in_desired" : 39.41,
         "internal_reserve_sub_ref2" : "",
         "cancellation_status" : "possible",
         "total_sale_seatprice_in_desired" : 367.83,
         "item_number" : 2,
         "total_sale_surcharge" : 45
      }
   ],
   "currency_details" : {
      "eur" : {
         "currency_pre_symbol" : "€",
         "currency_post_symbol" : "",
         "currency_number" : 978,
         "currency_code" : "eur",
         "currency_places" : 2,
         "currency_factor" : 100
      }
   }
}
from pyticketswitch.cancellation import CancellationResult
...

CancellationResult(
    must_also_cancel=[Order(
        item=2,
        backend_purchase_reference='PURCHASE-286D',
        cancellation_comment='',
        cancellation_status='possible',
        event=Event(
            id='BPT',
            status='live',
            description="Moulin Rouge (Dinner Show)",
            source='External Test Backend 1',
            source_code='ext_test1',
            event_type='simple_ticket',
            venue='Bal du Moulin Rouge',
            classes={
               'attract' : 'Attractions',
               'theatre' : 'Theatre'
            },
            postcode='75018',
            country='France',
            country_code='fr',
            latitude=0,
            longitude=0,
            max_running_time=120,
            min_running_time=120,
            show_performance_time=True,
            has_performances=True,
            is_seated=True,
            needs_departure_date=False,
            needs_duration=False,
            needs_performance=False,
        ),
        performance=Performance(
            id='BPT-E6P',
            event_id='BPT',
            date_time=datetime.datetime(2019, 4, 01, 19, 00, tzinfo=tzoffset(None, 7200)),
            date_description='Mon, 1st April 2019',
            time_description='7.00 PM',
            has_pool_seats=True,
            is_limited=False,
            is_ghost=False,
            running_time=120,
        ),
        price_band_code='A/pool',
        ticket_type_code='CANCAN',
        ticket_type_description='Menu French Cancan',
        ticket_orders=[
            TicketOrder(
                code='',
                seats=[
                    Seat(
                        id='YC472',
                        column='472',
                        row='YC',
                        separator='',
                        is_restricted=False,
                    ),
                    Seat(
                        id='YC473',
                        column='473',
                        row='YC',
                        separator='',
                        is_restricted=False,
                    ),
                    Seat(
                        id='YC474',
                        column='474',
                        row='YC',
                        separator='',
                        is_restricted=False,
                    ),
                ],
                description='',
                number_of_seats=3,
                seatprice=140.0,
                surcharge=15.0,
                total_seatprice=420.0,
                total_surcharge=15.0,
            ),
        ],
        number_of_seats=3,
        total_seatprice=420.0,
        total_surcharge=45.0,
        seat_request_status='not_requested',
        send_method=SendMethod(
            code='POST',
            cost=10,
            description='Post worldwide',
            type='post',
        ),
    )]
)

The cancellation_status for each order item will become cancelled if it has been cancelled. Some items are not cancellable, their cancellation_status will be not_permitted in the API requests before cancellation (e.g. purchase and status) and after the cancel API request. If the cancellation of an order item is tried and fails then the order item cancellation_status will become tried_and_failed. In some circumstances the call might return the must_also_cancel list, which means that you must also specify the items in that list in order to cancel the items that you requested to cancel originally.

Attribute Description
cancelled_items_list This will list the items that were cancelled in this API request (note that this is not idempotent: items will only appear in this list the first time they are cancelled).
must_also_cancel This is a list of order items that must also be cancelled in order to sucessfully cancel the transaction.
trolley_contents The trolley object. The trolley attributes are as described in the purchase response. Note that if the transaction_status is released you should ignore the value of minutes_left_on_reserve.

Suppliers

Definition

GET https://api.ticketswitch.com/f13/sources.v1

Retrieve the list of supplier systems that are used to source the events you have access to. Events can then be filtered by using e.g. https://api.ticketswitch.com/f13/events.v1?s_src=ext_test1.

Cities

Definition

GET https://api.ticketswitch.com/f13/cities.v1

This call is not currently available - it will be added soon.

Classes

Definition

GET https://api.ticketswitch.com/f13/classes.v1

This call is not currently available - it will be added soon.

Bitmask Fields

This section describes the bitmasks fields returned in response to some API calls and explains how to decode their data.

The ‘bitmask’ fields are compact representations of arrays of flags, where the binary digits of the number represent true and false flags as 0 and 1.

We number our bits in the conventional way with the least significant bit being bit zero.

The correspondance between bits numbers and actual things is:

  1. For weekdays, 0 = Sunday, 1 = Monday, 2 = Tuesday etc…

  2. For months 0 is not used, 1 = 1st, 2 = 2nd, 3 = 3rd etc. (Note that this means all month bitmasks will be even numbers).

  3. For tickets, 0 = first ticket, 1 = second ticket, like an array index

Check check one of the bits in the bitmask you can use the following syntax in most languages: ((1 << bit_number) & bitmask)

For example if the API returns 91 as a weekday bitmask you could make the following checks in Python.

There is availability on Sunday:

>>> ((1 << 0) & 91)

1

There isn’t availability on Tuesday:

>>> ((1 << 2) & 91)

0

There is availability on Saturday:

>>> ((1 << 6) & 91)

1

Caching

Ingresso cache data at these levels:

  1. Events
  2. Performances
  3. Availability

Caching for events and performances

Ingresso cache two data sets for events and performances:

a) Approximately every hour Ingresso request events and performances from the individual supplier ticketing systems - any new events or performances are automatically added to the Ingresso database. New events are supplemented with images, descriptive content etc by our setup team and then go live, but performances automatically go live. When you request events or performances this request is answered directly from the Ingresso database; we do not pass the request on to the supplier ticketing system.

b) Every time an availability request is made, Ingresso recalculate cost ranges. Cost ranges include a minimum and maximum price and details of any offers. Since they are built from availability requests, they are not necessarily accurate (for example if a new cheaper performance is added but availability hasn’t yet been requested for that performance, then the cost range for the event will not be accurate. We have processes to keep these up to date in some cases, but they are not guaranteed to be present. Cost ranges are described in more detail for example in the event cost range section.

Caching for availability

Availability is cached for a short period of time (usually 90 seconds). If for example your end customer selected the 1st March 7.30pm performance, then selected 2nd March 7.30pm, then selected 1st March 7.30pm again at this point the availability cache would be hit (assuming it was within 90 seconds of the first request). This is to avoid overloading the supplier ticketing systems during periods of high demand, for example an on-sale. The availability cache is cleared when tickets are reserved, so the cached availability is unlikely to be inaccurate.

Other caching requirements

If the above caching does not solve your problem, or if you have other caching requirements, please get in touch!

Do not go away and implement your own caching system that continuously makes availability requests to Ingresso, without discussing this with us in advance. This puts more load than necessary on the supplier ticketing systems, and can therefore reduce the throughput that we can offer. It is more complex than partners often first anticipate, for example it normally takes a lot longer to scan all performances for all events than partners imagine, and there are a number of edge cases that are easy to miss, e.g. avoiding retrying when a supplier system is under load or returning errors. We will consider closing the API accounts of anyone doing this without prior approval.

Transaction Reporting

Definition

GET https://api.ticketswitch.io/transactions.v0?from=2017-06-01

The transaction reporting resource allow you to retrieve, filter and order your transactions. This can be used, for example, to regularly populate your own database of Ingresso transactions.

  1. Pagination
  2. Time filters
  3. Other filters
  4. Ordering

Pagination

Definition

GET https://api.ticketswitch.io/transactions.v0?page_number={page_number}&page_length={num_items}

By default the returned dataset is paginated and limited to 10 records per page. To iterate over the pages supply a page_number=x query parameter where x is an unsigned integer. If this parameter is not passed the page will be set to 0 by default. To change number of records returned per page pass page_length=y, y being an integer. The maximum number of records per page is 100.

Example request

curl https://api.ticketswitch.io/transactions.v0?page_number=2&page_length=20&from=2017-06-01\
    -u "demo:demopass" \
    -X GET

Time Filters

Definition

GET https://api.ticketswitch.io/transactions.v0?from={date}&to={date}

The transactions API allows from and to query parameters to be passed to filter by the purchase time (purchase_time_utc). The time values supplied can either be passed as UTC timestamp or as a more human readable format in simplified ISO 8601 in a form of <YYYY>-<MM>-<dd>T<hh>:<mm>:<ss> (also in UTC timezone) where hours, minutes and seconds are optional and will default to either 00, 00, 00 in the case of from parameter or 23, 59, 59 in case of to if not passed.

For example to retrieve the records from September 29th 2017 at midnight (00:00:00) the following time parameter values are valid:

For partners using this resource to maintain a full database of Ingresso transactions we recommend that you:

Example requests

curl https://api.ticketswitch.io/transactions.v0?from=2016-01-02T14:33:22&to=2016-06-03T14:25:21\
    -u "demo:demopass" \
    -X GET
curl https://api.ticketswitch.io/transactions.v0?from=1506623211&to=1507643200\
    -u "demo:demopass" \
    -X GET

Other Filters

Definition

GET https://api.ticketswitch.io/transactions.v0/filter:{filter_options}'

The API allows you to use filters besides the purchase time. Currently the following filters are available:

If you would find other filters useful please contact us

To pass a filter option insert /filter:{filter_options} after /transactions.v0. All options are passed as key=value separated by ,. For example: /filter:event_id=44AP,supplier_code=nimax. The comma separator corresponds to the AND logical statement; so in the above example only records with event_id equal to 44AP and supplier_code equal to nimax will be returned. If the value contains white space then enclose it in single quotes '.

Example request

curl https://api.ticketswitch.io/transactions.v0/filter:event_id='44AP'\
    -u "demo:demopass" \
    -X GET
curl https://api.ticketswitch.io/transactions.v0/filter:event_id='44AP',supplier_code=nimax\
    -u "demo:demopass" \
    -X GET

Ordering options

Definition

GET https://api.ticketswitch.io/transactions.v0/order:{order_options}

To order returned data insert /order:<order_options> after /transactions.v0 using the set of fields you want to order by. A list of ordering fields should correspond to keys in the returned transaction records separated by ,. By default the data is ordered descending, if you wish to order it ascending prepend the field name with a $ character, for example $event_id,purchase_time_utc will order the data alphabetically by event id. If there are 2 records with same id those records will be ordered descending by purchase time. The following ordering options are supported:

Example request

curl https://api.ticketswitch.io/transactions.v0/order:event_id,supplier_code?from=2017-06-01\
    -u "demo:demopass" \
    -X GET

Response

Example API reponse

{
    "status": "success",
    "count": 10,
    "message": "",
    "data": [
    {
            "transaction_id": "T000-0000-ABCD-EFGH",
            "item_number": 1,
            "user_id": "demo",
            "backend_purchase_reference": "123456",
            "event_id": "2GXJ",
            "event_desc": "Wicked",
            "event_country_code": "uk",
            "venue_desc": "Apollo Victoria",
            "supplier_code": "atg",
            "purchase_time_utc": "2017-01-01T09:58:40Z",
            "purchase_time_london": "2017-01-01T09:58:40Z",
            "performance_local_time": "2017-01-02T19:30:00Z",
            "perf_type_code": "748418",
            "ticket_type_code": "CIR",
            "ticket_type_desc": "Dress Circle",
            "price_band_code": "A",
            "discount_desc": "Regular Price",
            "send_code": "H",
            "send_desc": "E-ticket (print at home yourself)",
            "seat_ids": [
                "J20",
                "J21",
                "J22",
                "J23"
            ],
            "trans_status": "normal",
            "sale_mode": "internal_credit",
            "debitor_reference": null,
            "user_can_use_customer_data": false,
            "supplier_can_use_customer_data": false,
            "num_tickets": 4,
            "num_transactions": 1,
            "sale_currency_code": "gbp",
            "sale_seatprice": 278,
            "sale_surcharge": 13.8,
            "ticket_price": 291.8,
            "send_cost": 0,
            "commision_currency_code": "gbp",
            "user_commission_inc_vat": 9.66,
            "gross_commission_inc_vat": 13.8,
            "inside_commision_inc_vat": 0,
            "supplier_levy": 7,
            "supplier_fee": 0,
            "supplier_rebate": 0,
            "surcharge_non_commissionable_postage": 0,
            "surcharge_commissionable_postage": 0,
            "processing_fee": 0,
            "supplier_uplift": 0,
            "user_uplift": 0,
            "customer": {
                "first_name": "John",
                "last_name": "Doe",
                "address_line_one": "Butterwick 1",
                "address_line_two": "Hammersmith",
                "town": "London",
                "county": "Greater London",
                "country_code": "uk",
                "postcode": "W68DL",
                "work_phone": 1234567,
                "home_phone": 1234567,
                "email": "customerservices@ingresso.co.uk"
            }
        }
    ],
    "timestamp": "20171004150512",
    "_meta": null
}

Results

Attribute Description
status String representing the status of the response (along with an HTTP status code). Can have following values: success, error, warning, debug
message Optional message, usually contains detailed error information if status is set to error.
count Number of transaction records returned.
timestamp UTC time in a form of YYYYMMddhhmmss.
_meta Object containing additional data, if supplied.
data List of objects containing transaction records, defined below.

Each transaction record returned from the API will have the following keys set:

Name Description
transaction_id The primary Ingresso transaction reference.
item_number A unique sequential number for the order. The second order added to the trolley will have item_number 2. The combination of transaction_id and item_number is unique.
user_id The user for which the transaction was made.
backend_purchase_ref The purchase reference from the supplier ticketing system.
event_id Unique identifier for the event.
event_desc Name of the show or event e.g. The Lion King.
event_country_code Code for the event’s country.
venue_desc Description of the event’s venue.
supplier_code Name of the backend system purchase was made with.
purchase_time_utc Purchase time (UTC).
purchase_time_london Purchase time (London timezone).
performance_local_time Performance time in the timezone local to the event.
perf_type_code Internal code.
ticket_type_code The unique identifier for the ticket type. For attractions this can refer to variations such as General Admission or Fast Track, and there is often only only. For seated events this normally refers to a part of house / seating area such as Grand Circle.
ticket_type_desc The description for the ticket type displayed to the customer.
send_code Send method code.
send_desc Description for the send method.
seat_ids Array containing list of purchased seats.
trans_status Status of the transaction - one of normal, test, refunded, partially-refunded, exchanged-original, exchanged-replacement (for exchanges the old booking is marked exchanged-original and the new booking marked exchanged-replacement), cancelled-performance, exchanged-venue-system-only (this is rare but covers the case when a booking is exchanged within the venue system so there is no record of the new tickets within the Ingresso Platform).
sale_mode The mode used to purchase tickets. Will be internal_credit if the sale was made on credit or external_redirect if the sale was made using Stripe or with a redirect.
debitor_reference If using Stripe this will be Stripe’s Charge ID.
user_can_use_customer_data Data protection question - set to true if the customer has opted in to receiving marketing emails from you.
supplier_can_use_customer_data Data protection question - set to true if the customer has opted in to receiving marketing emails from the event provider.
num_tickets Number of purchased tickets.
num_transactions This will be 1 for the first item in the order and 0 for the rest.
sale_currency_code ISO 4217 three letter code that applies to the sale_seatprice, sale_surcharge, ticket_price, send_cost.
sale_seatprice The total face value for this order.
sale_surcharge The total booking fee for this order.
ticket_price sale_seatprice + sale_surcharge
send_cost Send method cost.
commission_currency_code ISO 4217 three letter code that applies to all of the following commission attributes.
user_commission_inc_vat The commission earned for this transaction (all commission amounts are totals, not an amount per ticket).
billable Whether or not a charge was or will be applied to the transaction

The following fields are only returned for users that have permission to view detailed commission information:

Name Description
gross_commission_inc_vat The total commission available (Ingresso’s commission + user_commission_inc_vat).
inside_commision_inc_vat The total inside commission (commission paid by a supplier from the sale_seatprice).
supplier_levy The total restoration levy or venue facility fee.
supplier_fee A fee paid to the supplier.
supplier_rebate Another type of fee paid to the supplier.
surcharge_non_commissionable_postage A postage fee that is added as part of the sale_surcharge and excluded from commission calculations, not used by most partners.
surcharge_commissionable_postage A postage fee that is added as part of the sale_surcharge and included within commission calculations, not used by most partners.
processing_fee A processing fee, not used by most partners.
supplier_uplift Uplift is an additional charge on top of the ticket price for an upgraded experience. This is the uplift component earned by the supplier.
user_uplift This is the uplift component earned by the partner.

The customer fields are only returned for users which have permissions to see detailed customer data - by default these fields won’t be included - if you would like them included please contact us

For testing you can use the user demo-customerdata (password demopass). You can purchase with this user the same way you can with demo, however note that any customer data you enter when purchasing will be visible by everyone, so do not enter any data you do not want the internet to see.

Name Description
first_name First name of the customer
last_name Last name of the customer
address_line_one First line of customer’s address
address_line_two Second line of customer’s address
town Address’ city
county Address’ county
country Customer’s country
postcode Customer’s postcode
home_phone Customer’s home phone
work_phone Customer’s work phone
email Customer’s email