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 Ticketmaster Theatre and 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

F13 API Browser

F13 API Browser

We have also developed the F13 API Browser.

Basic booking flow

The Ingresso API is designed around booking seats for theatre product, and some of the parameters may use language (e.g. seat) reflective of that. However, it is flexible enough to be used 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://demo.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://demo.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://demo.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://demo.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://demo.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://demo.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://demo.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. A lot of the systems that our API connects to are very 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 TicketSwitch system 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 best available booking flow

At a minimum, the customer must be able to specify the number of seats they want and for which ticket type and price band. The Ingresso backend will then reserve the best available seats 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 seat 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 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 seats if customer does not proceed with the booking flow

A customer may change their mind about the number or type of seats to be reserved for a performance. If your customer selects and reserves seats, then goes back to select and reserve additional seats or removes the reserved seats from their basket, the initial seats 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 seat reservation has been released.

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

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 seats 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 seats 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 allow_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 email api@ingresso.co.uk 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:

Versioning

The API version number forms part of the URL, for example https://demo.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://demo.ticketswitch.com/f13/events.v1

Request

Example request

curl https://demo.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).
include_dead 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_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_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_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_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,
        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,
        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. 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.
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.

Events by ID

Definition

GET https://demo.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://demo.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://demo.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_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_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_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_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_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_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_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,
                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,
                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,
                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,
        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://demo.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_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_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://demo.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_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_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://demo.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_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_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 api@ingresso.co.uk. Cost ranges are only ever returned as part of a parent object (such as event).

Request

Example request

curl https://demo.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_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_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://demo.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_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_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 api@ingresso.co.uk.

Request

Example request

curl https://demo.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_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_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://demo.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://demo.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_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

{
  "results": {
    "has_perf_names": true,
    "paging_status": {
      "page_length": 10,
      "page_number": 0,
      "pages_remaining": 10,
      "results_remaining": 94,
      "total_unpaged_results": 104
    },
    "performance": [
      {
        "cached_max_seats": 6,
        "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"
      },
      {
        "cached_max_seats": 6,
        "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"
      },
      {
        "cached_max_seats": 6,
        "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"
      },
      {
        "cached_max_seats": 6,
        "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"
      },
      {
        "cached_max_seats": 6,
        "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"
      },
      {
        "cached_max_seats": 6,
        "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"
      },
      {
        "cached_max_seats": 6,
        "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"
      },
      {
        "cached_max_seats": 6,
        "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"
      },
      {
        "cached_max_seats": 6,
        "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"
      },
      {
        "cached_max_seats": 6,
        "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,
        cached_max_seats=6,
        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,
        cached_max_seats=6,
        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,
        cached_max_seats=6,
        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,
        cached_max_seats=6,
        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,
        cached_max_seats=6,
        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,
        cached_max_seats=6,
        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,
        cached_max_seats=6,
        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,
        cached_max_seats=6,
        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,
        cached_max_seats=6,
        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,
        cached_max_seats=6,
        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,
        cached_max_seats=6,
        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
cached_max_seats This is the maximum number of contiguous seats that can be booked for this performance, based on Ingresso’s cached data. Note that if the event supports seat selection you are not limited by the number of contiguous seats, so this value should be used in the context of best available only.
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 seats 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

Performances by ID

Definition

GET https://demo.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://demo.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 seats 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 api@ingresso.co.uk. Cost ranges are only ever returned as part of a parent object.

Request

Example request

curl https://demo.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": {
      "cached_max_seats": 15,
      "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,
        cached_max_seats=None,
        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 api@ingresso.co.uk.

Request

Example request

curl https://demo.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://demo.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://demo.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://demo.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 seating 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 api@ingresso.co.uk.

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://demo.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 seats the customer would like. If this is specified then 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 api@ingresso.co.uk
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 seated events this 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://demo.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://demo.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.

Request

Example request

curl https://demo.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://demo.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://demo.ticketswitch.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://demo.ticketswitch.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 seats the customer would like. If this is specified then only discounts valid for the number of seats 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://demo.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://demo.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://demo.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://demo.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://demo.ticketswitch.com/f13/trolley.v1 \
    -u "demo:demopass" \
    -d "trolley_token=U3--tgaXeGJ3jY8-7bxaEyEcKhrbmYsrFkLAQh2wn89J9IFevORBYwlCveIJxP51WpqbA0tih8NmBuDvAegm37cFhVZA7yIGKjbEIetqsk2z_MGFMfiY9f11oM3MOpxlcLLE7vehHd5qyL4ozVZNtTOtxrJHhntmDqb-SyNhtAD0xWakXhUPlGVqQvnqQ2feu0moVJ_Wn9ROLz8C6p65Epz6kxGYBaNg0zkAawIttK3IY1LbiRxEHS10-R-7f0FVbg9kq0X6S8oIiWwjCqYJ9OEktXo-bdasYe4wu0yfki9N4WmuDrpTBgOkS7618nMbTvpYzPPacne8hGRCmH6e3GjPRtvZAilpaol5rKX3zgjN30cpLpsXpFo7ZZkJXOr5YMj-rNTXs0xg3trhrePeOdFFjTuN06iHrX2W2ylETgQ4hS2uXZoBVNmg4R8IQqvq4xuMmvRMYz2kXkC5wJF7pAG9J0--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='E2--oMNQScXjk-RMutgBkigRHW70NMWzh6mFlEyGZ7AjUgdD3BeCgDem1JVsSOPEykxKN3heGSVE_IRvx63kEfhaTyi0EySnC_-Pqy9bcDpTtrBZEs-Durm_G94dvGoG64K2bAgTVCunIBmJk3fAwQYFFCSIEDKwx7tO4NeKdyg5Cd6_BS19n1BzeW5heK8UcmidlAwwVNA4LdDAImR9Uf_nUTUke35Fk44yOtWZti6HyZ4tmi5EnC4s-mLlnxkSP34tqBTqPdLlWwgWIbQBdcW2Umx4kl7lE0l02d7RmIiVK4zh9bfHpg5FrR2ravb8sQ-1vAQduh8GLzwbG-rt5y4qAfsCsKf5puh9Wx6FtL0sFz9-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://demo.ticketswitch.com/f13/trolley.v1 \
    -u "demo:demopass" \
    -d "trolley_token=M6--DqjJkw4ODNVbiWWjrfknLN1CB0WLJRnejw5mj18G6PEjAROXSlnHS56jA9qccvRUxTRu01vrc_bqz7f9YsDE6JDQ9rU6OvUQm7nAEvF-bX97lky1zH_b3UVk4HTJorjXeaPgrQRiXnWI76OP2vQ5ZlWFh1pZE_5P1aIlrSGGZmDQr3MLIkcNNJOfiDIx9Rsz3RUoH20SPlf-YvEcOn06Fk5le08fUpLC5fVkm1wCv0OejpHZcsdscg4WHLl8KphDMh7OFNAZ6oie6bxuiwX8Ni6cNNB3fmrlq73Ps2XPa-19n8eaJdEP0H6X_alL7E-Tja9c1AtEkccb49ig2d-ht1zdd1-BayxLPgeOFNC4-1cRXjQPiWWINzQDjUnzFn492WHBPjOvnFYqmboMjUdg-4BZ1vPNGeZzynq-dCh8h83AGCnctxu2qLOBPUc2ZCnCx5RvyJEwRb7iMklM5MxeKb8lYH8EM4RfqmD8JfTZTneiaxhxWOuBOAGml0cg7Nw2WNx_nlG6IVZKOZWNDhTqhCODLcdWjEKRnEQrfLnVk1JbYpFJ8JeF47KNTXVjXQW-MMBZyLgmrJ0G2BPAvzTUx1mU_WmRfs6givmewFw-enWXdYOodreJ0eT2awhGm0UYcxWK70DH5w4yGa_xSf8vUZjHIlMIPK_V6I4pSplYwRAp1EwgFgcbBwOlM_NKZQepEuZVf4VAfK8-Z" \
    --compressed \
    -G
from pyticketswitch import Client

client = Client('demo', 'demopass')
trolley, meta = client.get_trolley(
    token='E2--nPSMAQKI8kggWwF4N5qp4zPaO2VU_3armTREADiU6s4xgp3VjDmF7TXSnD0DN100souzOPZD8COW-jLhPSAsdOY-DhoK15T4meB5-xUrXpZ2cMrLIbVbongnwLqzJdI_-FFa6XqQTrF2ncjGLssB9nC7R79FHSN12AADiZ795WDj3vQ8GJ6DGvXjTf3-bULrCpjitgZLqMf_bAlqay7hSQxfCFaD1PiUtuU7gIhi7vnsr0CJT7vtJJmLd_HXfrwgQYTNey5dia6Tx9o4Ed3QAvwctSGBGVZ6g9qabWwRnTbBg8_TFuvY0vSvqPq31b30Dey_rLBKq4X1Ay2uNx3VJCs221wGGEvmlY5JoxhmKm5-Z',
)

Example request - removing the first order from the trolley

curl https://demo.ticketswitch.com/f13/trolley.v1 \
    -u "demo:demopass" \
    -d "trolley_token=M6--DqjJkw4ODNVbiWWjrfknLN1CB0WLJRnejw5mj18G6PEjAROXSlnHS56jA9qccvRUxTRu01vrc_bqz7f9YsDE6JDQ9rU6OvUQm7nAEvF-bX97lky1zH_b3UVk4HTJorjXeaPgrQRiXnWI76OP2vQ5ZlWFh1pZE_5P1aIlrSGGZmDQr3MLIkcNNJOfiDIx9Rsz3RUoH20SPlf-YvEcOn06Fk5le08fUpLC5fVkm1wCv0OejpHZcsdscg4WHLl8KphDMh7OFNAZ6oie6bxuiwX8Ni6cNNB3fmrlq73Ps2XPa-19n8eaJdEP0H6X_alL7E-Tja9c1AtEkccb49ig2d-ht1zdd1-BayxLPgeOFNC4-1cRXjQPiWWINzQDjUnzFn492WHBPjOvnFYqmboMjUdg-4BZ1vPNGeZzynq-dCh8h83AGCnctxu2qLOBPUc2ZCnCx5RvyJEwRb7iMklM5MxeKb8lYH8EM4RfqmD8JfTZTneiaxhxWOuBOAGml0cg7Nw2WNx_nlG6IVZKOZWNDhTqhCODLcdWjEKRnEQrfLnVk1JbYpFJ8JeF47KNTXVjXQW-MMBZyLgmrJ0G2BPAvzTUx1mU_WmRfs6givmewFw-enWXdYOodreJ0eT2awhGm0UYcxWK70DH5w4yGa_xSf8vUZjHIlMIPK_V6I4pSplYwRAp1EwgFgcbBwOlM_NKZQepEuZVf4VAfK8-Z" \
    -d "remove_items_list=1" \
    --compressed \
    -G
from pyticketswitch import Client

client = Client('demo', 'demopass')
trolley, meta = client.get_trolley(
    token='E2--nPSMAQKI8kggWwF4N5qp4zPaO2VU_3armTREADiU6s4xgp3VjDmF7TXSnD0DN100souzOPZD8COW-jLhPSAsdOY-DhoK15T4meB5-xUrXpZ2cMrLIbVbongnwLqzJdI_-FFa6XqQTrF2ncjGLssB9nC7R79FHSN12AADiZ795WDj3vQ8GJ6DGvXjTf3-bULrCpjitgZLqMf_bAlqay7hSQxfCFaD1PiUtuU7gIhi7vnsr0CJT7vtJJmLd_HXfrwgQYTNey5dia6Tx9o4Ed3QAvwctSGBGVZ6g9qabWwRnTbBg8_TFuvY0vSvqPq31b30Dey_rLBKq4X1Ay2uNx3VJCs221wGGEvmlY5JoxhmKm5-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 api@ingresso.co.uk.

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 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 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_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_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 seated events this 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 seats 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 seats for an event containing add-ons.

Definition

GET https://demo.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://demo.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 seats.
no_of_seats A trolley with a specified number of seats added.
perf_id A trolley with seats for the specified performance added.
price_band_code A trolley with seats 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 seats.
X_send_code A trolley with the specified send method for new tickets added.
ticket_type_code A trolley with seats 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_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,
        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 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.
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://demo.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 api@ingresso.co.uk.

Request

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

curl https://demo.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://demo.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://demo.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,
)

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.
reserved_trolley 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.

reserved_trolley 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.
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 seated events this 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 seats 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://demo.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 seats). 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://demo.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://demo.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 token or 3D Secure source generated on your checkout page, 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 token or source 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://demo.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" \
    --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.

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",
    "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,
    ),
)
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.
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 api@ingresso.co.uk.
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.
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 seated events this 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 seats 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 have been set up to produce your own self print vouchers (eTickets), false if you are using Ingresso-provided vouchers.
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.

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.

Purchasing with Stripe

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.

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

  1. Retrieve a Stripe token or payment source (further detail below).
  2. Save the Stripe token or payment source 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 token

Stripe collects payment information on your behalf, and returns a single-use token. 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.

For anti-fraud reasons, we recommend generating a 3D Secure payment source as per the Stripe docs, and this is one of the requirements for using the Ingresso Stripe account.

Saving the Stripe token 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_source": "src_ABCD1234",
    "stripe_source_amount": 6250,
    "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 stripeToken = "tok_visa";

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_token: stripeToken }));

Example response

{"token": "cider_XYZ789123"}

Once you have the Stripe token, 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 token or source 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 tokens 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

Retrieving the Stripe token 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://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. 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 token or payment source 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/stripeToken. 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",
            "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,
                        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.

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).

Purchase request

Example purchase request - generic redirects

curl https://demo.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" \
    -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://demo.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://demo.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.

Status

Definition

GET https://demo.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. An example use is to retrieve information to display on a confirmation page.

Request

Example request

curl https://demo.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",