Order webhook

Behaviour

In S-360 an order represents a transaction between a contact and the institution operating S-360. It can be a sale, a refund, a reservation, an option...

With this webhook activated, each time a order is finalized (closed or abandonned), S-360 backend calls a given url transmitting the order in the form of a JSON payload.

The strucure of the payload is defined in the following API getOrderDetails.

This behavior is asynchronous: the list of closed/abandonned order ids is stored in a queue, and this queue is processed every M minutes, with M between 1 and 1440.


Synchronization rate

When setting up the webhook, the operator defines:

  • the frequency M: the queue of pending changes will be processed every M minutes.
  • the batch size S: during each process, S orders will be processed.
  • the bucket size bs: a payload POST-ed to the remote URL will consist of a maximum of bs orders.

Default values:

  • M=15 minutes
  • S=100
  • bs=1

URL and HTTP method

The callee must provide an URL which will accept POST requests containg the JSON payload described below and return 200 when accepted.

If the URL returns values (an id, a message...), those values will be ignored.

If the URL returns an error, the same order will be sent every M minute, 12 times. After all those tentatives, the synchro will be abandonned, but the failed contacts will be logged.

Authentication

It is possible for S-360 to process an authentication on the remote URL. Here are the supported authentication protocols:

Modifying the content of the payload

Details

It is possible to select which order elements will be sent, with the following possible options.

  • OPERATIONS: content of the order: products, tariffs, quantities, advantages used...
  • MOVEMENTS: individual details for each operation: seat, ticket owner... (includes the preceeding)
  • TICKETS: tickets related to the movements. (includes the preceeding)

Other modifications

Other modifications, like changing the structure of the payload, keeping only certain fields, etc., is impossible. If you need a specific payload, you likely want a data export webhook.

Filter

A filter can be defined in the interface parameters to control the transmission of only the desired orders. This filter parameter contains a string, based on OrderDetailResult, like this below:

OrderDetailsData.OperationDatas(*).ProductCode=XXXX (if product code of any operation is XXXX)

OrderDetailsData.OperationDatas(ProductCode=XXXX).BasePrice=10000;OrderDetailsData.OrderType=SALE (if base price of the operation with product code XXXX is 10000 and the order type is SALE)

The delimiter of each condition in the filter is the character ";".

When a filter is added to the interface parameters, it's important to set the "Granularity" parameter (possible values in getOrderDetails method).

Setup in backend

  1. Ask for a proxy opening for the destination URL.
  2. In organization/tools/external interfaces create a new interface of type Firehose order
  3. Paste the url in the Url field
  4. Choose the authentication mode : NONE, BASIC_AUTH, API_KEY
    1. NONE : nothing else to do
    2. BASIC_AUTH : put the login in the login field, the password in the password field
    3. API_KEY : put the name of the header in the login field, the key in the password field
  5. Enter the desired granularity of the output result to be synced. By default: "TICKET"
  6. Save
  7. In the schedule menu, create a new schedule with a frequency fitting your needs and batch size of 60 (recommanded default value).

Order JSON example

In case of a bucket size greater than one, the payload will always be a list (surrounded with []), even if the payload only contains one element.

{
    "orderDetailsData": {
        "orderId": 10000702652,
        "orderState": "CLOSED",
        "creationDateTime": "2020-10-13T10:09:27.503+00:00",
        "referenceDate": "2020-10-12T22:00:00.000+00:00",
        "expirationDate": "2020-10-13T10:32:33.738+00:00",
        "saleAmount": 40000,
        "preSaleAmount": 0,
        "reservationAmount": 0,
        "optionAmount": 0,
        "waitingAccountBalanceAmount": 0,
        "operationDatas": [{
                "operationId": 10228310724422,
                "kind": "SINGLE_ENTRY",
                "quantity": 2,
                "basePrice": 20000,
                "unitPrice": 20000,
                "productId": 10228231108335,
                "product": "Arena Suite Dining",
                "productCode": "ASTDN",
                "itemId": 10228231110052,
                "performanceId": 10228231109243,
                "performance": "Arena Suite Dining",
                "eventId": 10228231108335,
                "physicalConfigurationId": 10228231107425,
                "siteId": 101053494751,
                "site": "S-360 Arena",
                "siteAddress": {
                    "firstAddressLine": "Route des Plaines-du-Loup 7",
                    "zipCode": "1018",
                    "locality": "Lausanne",
                    "countryCode": "CH",
                    "phoneNumber": "41-0213151414",
                    "gpsLatitude": "46.5333333",
                    "gpsLongitude": "6.6241666999999325",
                    "website": "http://www.secutix.com"
                },
                "space": "Home arena suites",
                "contingentId": 101053494560,
                "contingent": "VIP",
                "numbered": false,
                "seatCategoryId": 10228231108132,
                "seatCategory": "Cat 2",
                "seatCategoryRank": 1,
                "audienceSubCategoryId": 10228231110152,
                "audienceSubCategory": "VIP",
                "audienceSubCategoryRank": 1,
                "audienceSubCategoryRequireAttachment": false,
                "vatRate": 8000,
                "vatCountryCode": "CH",
                "selfPaidVat": false,
                "operationNumber": 2,
                "productFamilyType": "SINGLE_ENTRY",
                "productFamilySubType": "SPORTING_EVENT",
                "activityType": "SPORT",
                "performanceData": {
                    "10228231109243": "2020-10-31T16:00:00.000+00:00"
                },
                "performanceDate": "2020-10-31T16:00:00.000+00:00",
                "performanceDuration": 7200,
                "itemDisplayExternalDesignation": "Arena Suite Dining",
                "locations": [{
                        "spaceCode": "Suites",
                        "siteCode": "Arena",
                        "spaceExternalName": {
                            "translations": [{
                                    "locale": "en",
                                    "value": "Home arena suites"
                                }
                            ]
                        },
                        "siteExternalName": {
                            "translations": [{
                                    "locale": "en",
                                    "value": "S-360 Arena"
                                }, {
                                    "locale": "fr",
                                    "value": "Ar´┐Żne S-360"
                                }
                            ]
                        },
                        "siteAddress": {
                            "firstAddressLine": "Route des Plaines-du-Loup 7",
                            "zipCode": "1018",
                            "locality": "Lausanne",
                            "countryCode": "CH",
                            "phoneNumber": "41-0213151414",
                            "gpsLatitude": "46.5333333",
                            "gpsLongitude": "6.6241666999999325",
                            "website": "http://www.secutix.com"
                        }
                    }
                ],
                "fileId": 5464,
                "match": {
                    "finalDate": true,
                    "roundCode": "J1",
                    "roundRank": 1,
                    "hostTeamId": 101053521731,
                    "opposingTeamId": 101053521720,
                    "round": "Day 1",
                    "hostTeam": "Team Play",
                    "opposingTeam": "Athletico Fedora"
                },
                "withoutVatTotalAmount": 37040,
                "totalAmount": 40000,
                "performanceKind": "Default",
                "waitingAccountBalance": 0,
                "season": "Current season",
                "crossSellParentOperationIds": [],
                "comfortVariableValues": {
                    "PrioPts": {
                        "translations": [{
                                "locale": "en",
                                "value": "0"
                            }
                        ]
                    }
                },
                "performanceCode": "ASTDN",
                "audienceCatId": 15655,
                "seatCategoryBgColor": "FF8000",
                "seatCategoryTextColor": "000000",
                "exchangeable": false,
                "isNominative": false
            }
        ],
        "movementDatas": [{
                "movementId": 10228310724638,
                "operationId": 10228310724422,
                "barcode": "278777501804038390760100",
                "taxNumber": "01010089510",
                "type": "AREA",
                "seatCategoryId": 10228231108132,
                "seatCategory": "Cat 2",
                "contingentId": 101053494560,
                "contingent": "VIP",
                "areaId": 10228231107526,
                "saleAreaId": 10228231107931,
                "area": "Arena suite",
                "contactReference": "10912",
                "areaKind": "INDIFFERENT",
                "resumed": false,
                "attributionMatch": "NO_EXPECTATION",
                "externalReferences": []
            }, {
                "movementId": 10228310724637,
                "operationId": 10228310724422,
                "barcode": "337510583739402222630181",
                "taxNumber": "01010089509",
                "type": "AREA",
                "seatCategoryId": 10228231108132,
                "seatCategory": "Cat 2",
                "contingentId": 101053494560,
                "contingent": "VIP",
                "areaId": 10228231107526,
                "saleAreaId": 10228231107931,
                "area": "Arena suite",
                "contactReference": "10912",
                "areaKind": "INDIFFERENT",
                "resumed": false,
                "attributionMatch": "NO_EXPECTATION",
                "externalReferences": []
            }
        ],
        "movementTicketDatas": [{
                "movementId": 10228310724638,
                "ticketId": 10228310723729,
                "ticketState": "NOT_PRINTED",
                "barcode": "278777501804038390760100",
                "taxNumber": "01010089510",
                "contactReference": "10912",
                "ticketSupport": "THERMAL",
                "linkedToTicketDistribution": false
            }, {
                "movementId": 10228310724637,
                "ticketId": 10228310723728,
                "ticketState": "NOT_PRINTED",
                "barcode": "337510583739402222630181",
                "taxNumber": "01010089509",
                "contactReference": "10912",
                "ticketSupport": "THERMAL",
                "linkedToTicketDistribution": false
            }
        ],
        "contactReference": "10912",
        "salesChannelName": {
            "translations": [{
                    "locale": "en",
                    "value": "Box office - Test"
                }, {
                    "locale": "fr",
                    "value": "Guichet"
                }, {
                    "locale": "ca",
                    "value": "Kasse"
                }
            ]
        },
        "orderType": "SALE",
        "generatedContiguities": [],
        "orderOriginData": {
            "countryCode": "ES",
            "zipCode": "18010",
            "toCreateToken": false
        },
        "salesChannelType": "BOXOFFICE",
        "orderInstallmentsToCreate": [{
                "orderId": 10000702652,
                "dueDate": "2020-11-11T23:00:00.000+00:00",
                "dueAmount": 40000,
                "paidAmount": 0
            }
        ],
        "orderSecretId": "851b3217-c963-430a-b4fd-36d6a28fb504_10000702652",
        "orderOriginator": "SALE",
        "salesChannelCode": "BO",
        "catalogCurrency": {
            "currencyCode": "EUR",
            "symbol": "?",
            "fractionDigit": 2,
            "minAmount": 10
        },
        "organizationCode": "PLAY",
        "organizationName": {
            "translations": [{
                    "locale": "en",
                    "value": "MPLAY - TEST"
                }, {
                    "locale": "fr",
                    "value": "MPLAY - TEST"
                }
            ]
        }
    },
    "orderDetailGranularity": "TICKET"
}