NAV

Welcome

We are here to help!

contact-photo

Asmus Jacobsen
Partner Success Manager

partner@secra.de

Before you reach out for support, please make sure to answer a short list of questions.

Welcome to the SOAP API Documentation of our SECRA Destination system. This is the API for our integrated booking engine to make reservations or just retrieve data about the various properties.

Before you start, you need to request an account from our support at partner@secra.de. Please remember to describe your use-case, who you are and why you want access to our API.

Getting started

SOAP

As for testing, we suggest using SoapUI.

This is a SOAP 1.1 based API. You can use any capable SOAP client, which supports WS-Security header authentification. All of this is strictly following the standard, so you will be fine if you find a standards compliant framework.

API endpoints

The technical codename "USSOP" is a shorthand for Universal SOAP Service of the Optimale-Präsentation.

The SOAP API is split into three parts:

Core/Booking API

This is the main API for retrieving object details, prices and occupancy information. This is also used for real-time queries and bookings. For channelmanagers this is the API to set/update availability and prices.

Landlord-Management API

Here you can create and update landlord/host data. This API is mainly useful to you if you've got a large or highly changing landlord/object pool by yourself.

Object-Management API

This API provides access to creating and updating data of objects under an existing landlord.

You can use the same login for all three APIs, but your user account must be enabled to do so.

Which API should I use?

Which API to use depends on your role: If you are a classical sales channel you will need access to Core API, if you are a full content provider, you will need Landlord and Object APIs too.

Note: If you are only updating prices and occupancy and do not manage objects at an inventory level (e.g. you are a channelmanager), you will be fine with just Core API.

Before starting to implement you should read the corresponding technical API documentation (WSDL+XSD) to get an idea of what we provide.

Don't worry, we've got a human readable version of the WSDL+XSD for you too!

Versioning

All API endpoints are under Versioning. If new versions are deployed, the default version will move to the latest version. Our supplied WSDL files therefore always use Version-Pinning and so should you!

You can easily switch or pin the versions by supplying the required GET parameter v with the endpoint URL.

Example: https://www.optimale-praesentation.de/comm/universal?v=1.42

Access Level

Depending on your use-case you will be granted several access rights, either globally or per customer. If you perform an action you are not allowed to, you will receive an error, claiming that you have insufficient access rights.

If you receive an error and think this is an error / misconfiguration you can contact our support with the method you were trying to use, the property or entity which you were trying to modify and the name of your user account.

The following scopes are currently available:

Reading Access

Hint: Binding requests is a reservation operation mode where the host must accept/confirm a reservation request, otherwise it will be rejected. It is pretty much like true online booking but with a delayed acceptance.

Writing/Editing Access

Authentication

We do provide different authentication methods. You are free to choose the one you prefer or which one you are able to implement on your platform. Whatever method you choose, all connections must be encrypted. The interface will force any connection to use SSL/TLS.

Supported authentication methods (following the official WS-Security standard):

Rate Limits

This API is using Rate Limiting for Load Control. Currently there are 2 independent Rate Limiting levels. All Rate Limits emit Rate Limit Headers (see "RateLimit Header Fields for HTTP"). While the global limit uses the default Headers, the lower Write Limits use additional Custom-Prefixed Headers. All Rate Limits follow a fixed-window approach. You can easily get the current Limits by reading the respective Headers in any response to which they apply.

In general there are two response Headers that are especially useful to you: X-RateLimit-Remaining and X-RateLimit-Reset. You should at least parse these two Headers. For advanced Load Balancing and forward planning it is suggested to parse the X-RateLimit-Limit Header.

Example

Header Name Value (Example)
X-RateLimit-Limit 6000, 6000;w=600;burst=24000;comment="fixed-window", 36000;w=3600;comment="fixed-window"
X-RateLimit-Remaining 6000
X-RateLimit-Reset 378
XX-RateLimit-w600-Remaining 5999
XX-RateLimit-w600-Usage 1
XX-RateLimit-w600-Limit 6000
XX-RateLimit-w600-Burst 24000
XX-RateLimit-w600-Reset 378
XX-RateLimit-w3600-Remaining 35991
XX-RateLimit-w3600-Usage 9
XX-RateLimit-w3600-Limit 36000
XX-RateLimit-w3600-Reset 3378

X-RateLimit-* Headers

This is only a brief description of used Headers. Please read the documentation of standard Headers linked above if you have any more questions.

The remaining count will stay static while you use the burst Quota until the burst is used up. This means e.g. if burst is 24k and normal Limit is 6k, the remaining count will start to go down with the last 6k of the total 24k. The main reason for Rate Limiting is: Load Control. It is not intended for API Users to use burst all the time.

For your convenience we also supply some non-standard Headers:

For Write Limits there are identical Headers just prefixed with X-Write-RateLimit-*. They follow the same fixed-window approach and standard as the general Headers.

Global API Rate Limit

The global API Rate Limit applies to ALL requests and all APIs under this documentation. There are some scenarios, especially when doing fullsync operations of all data and entities, where you might reach the Limits if not optimized for Load Balancing and Quota Usage Monitoring. So reading the Rate Limit Headers in response is always a good idea, especially the X-RateLimit-Remaining Header should never hit zero.

The global rate limits are now dynamic and tailored per channel based on the number of connected properties. This allows for more efficient quota allocation: smaller channels receive appropriate limits without excess, while larger channels can scale accordingly. The limits are calculated as follows:

Base hourly limit: 18,000 requests (approximately 50% of the previous static limit). Scaling: 2 requests per connected property per hour. Effective hourly limit: The maximum of the base limit or the scaled amount (i.e., max(18,000, 2 × number_of_properties)). Manual overrides: A configurable factor (from 1.0 to 3.0 in 0.1 increments) can be applied to multiply the effective hourly limit, allowing for custom adjustments up to 3x the calculated value.

The number of connected properties is retrieved from a cached value in Memcache (permanent cache, with rare resets possible—in such cases, the base limit applies as a fallback). This calculation is not recomputed on every request for efficiency.

At the point of writing, there are 2 global limits with the following windows (the 600-second window remains static to prevent massive peaks, while the 3600-second window is dynamic):

What this means is: You can use the 24k requests in a 10 minute window, but not in every 10 minute window, as you would exceed the hourly Limit. The dynamic limits are reflected in the emitted Rate Limit Headers (e.g., X-RateLimit-Limit will show the current effective values).

Unique Write Rate Limits

The current Rate Limit for some Write requests (setPrices, setCategoryOccupancy) are:

This Rate Limit will emit its own custom-prefixed Header (X-Write-RateLimit-*).

Exceeding the Rate Limit

If you have exceeded the Rate Limit your requests will be dropped and we will return a response with HTTP status of 429 ("Too Many Requests"). If you hit this Limit there is nothing our Support-Team can do for you, you must wait until the next Window. Please keep in mind that dropped requests still count for your usage.

Other Limits / Non Rate Limit limits

Please keep in mind that for some methods there are additional usage Quotas, e.g. the number of Entities you can create or request.

Error Handling

In general, these APIs emit errors when there is something wrong. The only exception are bulk requests where failing parts are silently dropped to not drop all data for hundreds of properties. Keep in mind that we can also only detect formal not logical errors in your requests.

The APIs differentiate between hard syntax / usage errors and "soft" errors which mostly are caused by the content / values which have been submitted (e.g. an email address wasn't able to pass DNS validation checks but was formally correct).

It is often overlooked that responses with status code 500 do have a payload, because most frameworks just skip reading the body of the response in such cases. Doing so with SOAP Exceptions will keep you from reading valuable error codes and messages!

You can find a full list of all error codes here.

Receive Data Updates

The desired way of receiving notifications for data changes of any kind are Webhook Callbacks, called "Push Events", as we push the event to your Callback URL.

You can (and most likely should) register for Webhooks for Updates regarding the following topics:

Registration is done by providing our support with the 3 public(!) URLs you want to use as Webhook receivers. You can either use one for all or three separate URLs. Webhooks will be called using GET requests only.

Good to know: Your receiver URL may contain any number of own GET parameters, we will extend those with the ones to be submitted to you.

We only submit ...

Webhooks never transfer confidential data directly. They are intended as triggers for you to fetch specific updates, so you can stay up-to-date in close to realtime. They are intended as a way to keep your data in sync between weekly fallback full syncs of all data.

Our send mechanism can cover short outages at your end and will try to resubmit after a short delay. We usually plan for covering around 1 hour outages (although we do in fact cover larger ranges, we do not guarantee to do so).

Depending on how many properties are in your scope the number of webhook events might be relevant for your design decisions, as we do transmit nearly all events in close to realtime with only microseconds of delay. Be aware that we highly suggest enqueuing and deduplicating those events when received as our senders only have a small timeout (15s) and then assume the delivery attempt to be failed. As we submit in realtime there is no real chance at our end to deduplicate these.

For most events we run a number of concurrent workers, so expect some connections to be done in parallel.

As this is only a short teaser of our Push Events, please see the separate topic for more details.

More on Webhooks / Push Events

Implementation Guides

Now that you've read all those Basics, the next question is: Where do I start? Which methods and APIs do I choose? The answer is: That depends on your Use-Case. We provide some short Introductions to the most common Use-Cases.

Guides / Walkthrough

Specification / WSDL

Core/Booking API Specification

Version Link
Function Reference Link
ZIP Download
WSDL Link

Landlord-Management API Specification

Version Link
Function Reference Link
ZIP Download
WSDL Link

Object-Management API Specification

Version Link
Function Reference Link
ZIP Download
WSDL Link

Guides

General Informations

For all variations of implementations you will need to:

You will find most of this information in the "Getting started" section or at least some introduction and links to more details.

How do I progress from here?

If you've read all the "Getting started" topics the next question is, what to do next? Generally speaking you need API credentials and you need to request access to test/demo data from our support. In most cases you will receive a backend login too, so you can compare what the UI shows to what you've read or wrote to or from our API.

You can try and find out which calls to use on your own from the human-readable function reference directly, but we highly suggest you save yourself a lot of time. Over the years the API gathered a quite huge call collection and in most Use-Cases you are only going to use very few of them.

So let us first cover some basics:

Your first call will be getState. getState is giving you a list of all properties you have access to, your "pool". This "pool" will change over time: You will get access to new properties in it and you will lose access to some. If you lose access it is required that you remove the properties at your end, this means at least that they aren't accessible in any public way. This includes images and deeplinks! Make sure to do this in a reasonable amount of time (e.g. 24 hours).

There is no Push Event for losing access, so the only way is to diff the result of getState in some way and see what is new, what is missing and what has changed.

So with getState you now know a lot of IDs. The main identifiers you always want to save here are category_type and category_no. Make sure to store both. category_no alone is not unique as the numbers for the different types originate from different primary keys.

You will also notice organisation_no which is marking the customer account at our end and the object_no which identifies a single property. Each property can contain multiple category items and each category can contain multiple units (e.g. rooms). If you come from a sole apartment view this might at first look confusing, but keep in mind that we also cover hotels under the same scheme. So from the APIs perspective a single apartment is just one object, with one category and one unit in it. For hotels you can have multiple categories (e.g. different room types) and of course there is more than one unit within the categories.

To summarize:

ID Explanation
organisation_no The customer account at our end from whom the data originates
landlord_no The specific host under the organisations account
object_no The ID of the property
category_no The ID of one category inside the property
category_type The type of the category_no (e.g. the index it is derived from and in which the ID is unique)
unit_no ID of a single room inside the category

Sales Channel Guide

What is a Sales Channel in terms of API usage?

You are a Sales Channel to us if you read property, price and availability data and the only thing (if at all) you write back are reservation (requests). If you write prices or any other data that is more in a property management role, you are a Channelmanager to us (there is a guide for you too!).

Walkthrough: Steps for fetching Data and Reservation Workflow

So you've got a list of IDs from getState and want to read the required data for a typical property details page or a search result listing.

You will find two main methods to call for this: getObjectDetails and getCategoryDetails. Both support bulk requests. We usually suggest batches of 100 items at once. Batching requests is very important if you want to stay within the Rate Limits. If you fail to do so you will have a hard time on huge property pools. In general, if you use bulk requests wherever possible (and it is supported widely across the API) you will have no worries with the Rate Limits.

With bulk or batch calls you need to keep in mind that response time will rise, so make sure your timeout is sufficiently high for the size of the batch that you are requesting. Low timeouts are a common support issue when "receiving no response!". In fact there was a response, but the timeout was too low. Also keep in mind that the response times of the API may vary based on overall system load due to other consumers.

From getObjectDetails and getCategoryDetails you will receive a lot of details, including images, prices and so on. Even a direct booking URL, if you choose to not implement your own reservation flow, you can use that link and just redirect the potential guest to it. However, most partners choose to do their own implementation or integration with their existing web interface.

Using the previous two methods you can also calculate a price range. It is expected to filter as much as possible at your end. While there are also batch calls for price calculation, these calls will have a hard time to keep up with the full traffic of your website / portal / etc..

The next thing, and maybe the first thing you want to use for filtering, is availability. You can fetch this data from getOccupancy. You will receive "free" (available slots) for each category you've requested. Make sure to store this and use it locally at your end, this also applies to the property data from the previous calls. Never do live requests for these upon page visits. Instead, register for Push Events / Webhooks to get informed about changes and then only request the changed dataset.

You will notice that each property (object) has a map of features (properties) for things like e.g. Wi-Fi or Cooking Tools. These features are completely free to configure and name at our end on a per-organisation level. To give you a chance to auto-detect updates, we provide getProperties, which does nothing more than returning a per-organisation list of all available choices. Using this call is completely optional as it does not contain any new data besides the full feature flag matrix, but it is useful for automated checks.

At this point you have everything for object presentation. Use caching / your database where possible and keep data in sync with Push Events. Also adding a weekly full sync beside the updates is always a good idea to have some failsafe option if you missed some event for whatever reason. A nightly job to diff getState and process changes is also a reasonable idea most of the time.

When you are done with importing the properties you can use setCategoryParam to push back a deeplink to the public presentation page. This call also supports adding various status details. The minimum to implement would be to fill in values for "details_url", but "cause_of_rejection" is also welcome (human-readable short error message) as are all the other options too. The details_url value is displayed to the customer and host and makes life for both our support teams much easier!

So in short...

Method Description
getObjectDetails fetch base property / object data, images, etc.
getCategoryDetails fetch category data and prices/seasons
getProperties optional: fetch feature matrix
setCategoryParam add URL and status details back to us

After implementing the presentational part of the connection, the next step is proceeding to the reservation workflow.

When a page visitor is requesting more details or an offer for one specific property you use checkAvailability with the desired travel date ranges for arrival and departure, the number of persons and so on. The result is a positive or negative response and a base price calculation (not the final price as this would need more details).

IF the result is positive and the visitor wants to take the offer and proceeds in your reservation flow, the next call is getBookingParameters. Here you can supply more details and also get a list of available bookable extras. Supporting these (means: offering those to the customer) is highly suggested. While there are extras that must be booked, there are also optional or included ones. The price of these options might scale per stay, person or night - or a combination.

As an extra you can use getVisitorstax to calculate the visitorstax if there is a visitorstax_zone node in getObjectDetails which is not null. In that case we can calculate the tax for you. Note that the tax will be added to the reservation regardless of what you do, if the system is configured to include it. You can see if the tax was included in the reservations calls response with the calculation details. If you want to read the tax rules you can use getVisitorstaxRuleset to fetch them. It is not suggested to recreate the calculation at your end, but for guest information reasons the rules might be useful.

If the visitor and potential guest has made his decision, the next step is to actually do the reservation. There are two calls for this: makeBooking and makeRequestBooking. You will find that beside the name both are using the identical input and also deliver the same output. So why two different calls? The main reason is to make absolutely clear, that a request booking needs confirmation and therefore needs to display a lot of different information to the guest upfront. A requested booking can be rejected by the host (there is also an auto-reject mechanic if the host simply does not respond within a few days, but average response times are much lower). Opposed to that makeBooking is true online booking and when you receive a positive response the reservation has been made. You can filter out the different reservation modes by using the feature flags in getState response, so you skip importing these properties all together or you can group them as needed by you.

During the reservation flow there are a few things to keep in mind:

Now, after the reservation has been placed, you might want to track it. With the reservation response you received the booking_no, which is the reservations ID. You will want to store this number. You will also get some pricing details back, especially the brokerage_base_price is of use to you as this is the price which is used to calculate the brokerage amount you get.

If you add your own reservation numbers (and maybe communicate these to the guests as well), it is suggested to use attachExternalBookingNo to your newly created reservation. This allows for easier support as we will display the number or code to the backend users. It also simplifies communication for the support teams for everyday tasks.

Using Push Events for Bookings you can stay informed and use getBookingExtendedInfo to fetch the new Details, e.g. if the reservation is cancelled, extended or modified in any way. This is of course reflected to the brokerage_base_price.

Method Description
checkAvailability check free/occupied state and a first price
getBookingParameters fetch full offer options
calculateVisitorstax calc tax based on input
getVisitorstaxRuleset reads the base rules for tax calculation
makeBooking perform the reservation
makeRequestBooking perform a binding request for a reservation
attachExternalBookingNo add your own reservation Id
getBookingExtendedInfo fetch reservation data for updates on events

Channelmanager Guide

What is a Channelmanager in terms of API usage?

You are a Channelmanager if you write data on behalf of your customer, who is registered as host in our system. Typical Use-Cases include updating prices and/or availability. In most cases this includes reading new reservations using the API for further processing at your end. You do not write new reservations to the system, besides updating the availability.

Walkthrough: Steps for Data Updates

In a first step you should get the list of accessible properties from getState as mentioned in the "general" section of this guides chapter. Only properties which are on this list are enabled for your account.

In general, when a host wants to connect his existing properties in your and our system you have to ask him for some information:

You can make this process easier for the host when you just ask for the landlord_no and then use getState to fetch the properties, maybe even enriched by a following getObjectDetails call to fetch the names of the properties for a more user-friendly display to chose from for the host.

Additionally, you need your API credentials.

With the numbers available you must then choose between two options:

If you chose to write per unit, you will need the getUnits call to fetch the units for the connected categories and add them to your mapping database. You can then use setOccupancy to write availability per unit.

If you chose to write per category, you can simply use setCategoryOccupancy. In this case availability is automatically split to units, e.g. they are filled up one after another. This is usually the better option unless you need more detailed control over the process.

Note that you can not overwrite internal occupancy plan states (e.g. reservations). These are write protected. Depending on your access level, reservations are auto-blocked after cancellation to allow you to only free the timeslots if you wish to do so and if there is still availability.

If you are not allowed to write availability, the timeslot is freed after cancellation.

The next step is then to write season data and prices. This starts of with a call to setPrices to write the base occupancy, age range limits, prices, seasons, extra costs per person and other things needed to calculate a price. You will also want to use setCatering for catering options and seasons (independent of the ones in setPrices). As a last step, use setAddons to write additional services to the system (e.g. extra linen or other optional services, even mandatory services if you want them to be presented seperated from the base price or if they need to be paid per person or night). Keep in mind that all the calls above support writing more than one set at a time.

Using Push Events for Bookings you can stay informed and use getBookingExtendedInfo to fetch the new Details for further processing.

Method Description
getUnits fetch the units for a category
setOccupancy write occupancy per unit
setCategoryOccupancy write occupancy per category
setPrices write base pricing details and season data
setCatering write catering options
setAddons write addon options

Content Provider Guide

What is a Content Provider in terms of API usage?

If you do not only update data on behalf of a host, but you are also creating the host and/or property in our system, then you are a Content Provider. From the API view you are just a Channelmanager with extended access, but since this role uses different APIs we decided to provide you with a more detailed guide. However, for the data update part the Channelmanager guide is fully identical for your role.

Walkthrough: How to add hosts and objects

For the creation of new hosts you need to use the Landlord-Management API.

First you can use getRegions to fetch a list of available regions. If you only create hosts in an organisation without regions enabled, you will not find any matching results here. You can then skip the region code node when creating a host.

With getLandlordLanguages you can fetch a list of supported spoken language options for your host-creation or update call.

You use createLandlord to create a new host. For some fields you will need to have the IDs ready from our support (e.g. marketing and organisation_no). If you want to create objects for this new host also, remember to enable that option in the "services" section, otherwise you will not be able to do so using the API.

In the following response you must store the landlord_no, organisation_no and the authcode. Send the password to the host and do not store it yourself. If you do not want the host to have access to our Web UI, you can drop the password. You do not need it for API access.

If you want to update the host data you must use updateLandlord.

Using getLandlords you can fetch a list of "your" hosts if you need to.

At this point you have created a new host. The next step is to then create objects for this host, if you need to.

Before you create an object you must understand that there are three different states for objects.

Use makeObject to create a new object for an existing host. If you created the host, this is where the authcode comes in. If you did not create the host, you need to request the authcode from the host. You will find other required data in getDistances and getHolidayThemes for local distance options (e.g. distance to next store or beach) and configured topics you want to join the new object to (e.g. beach holidays or city trips). Both options are customized per organisation. If you want to read all features which are supported by the API you can use getProperties (note: this does not mean objects in this context) call from Core API.

Your newly created object will be unpublished in review state. Add/modify more data as needed and when done use moveOnline call to switch the state to online.

To forget the moveOnline call is a common error. So if you miss your objects in the different channels, check if it is still in review state. Note that you can always call moveOnline if you are unsure. It will simply do nothing if the object is already online.

To change any data for an object use updateObject call. Unlike the host update, you should only write data which has changed as this is expected to happen more often.

Finally, if you want to remove the object from channeling, use moveOffline call. Note that object removal is only available to our support and is only suggested if there are no open invoices, reservations and so on. Most likely you want to wait for some months after moving the object offline and only remove it then.

After this point you will only want to update prices and occupancy from time to time. See the Channelmanager guide on how to do so. The only difference is that you don't need the host to supply the required IDs if you created the host yourself.

Online Payment Workflow

Normally, all properties are working with invoices and bank transfer, but besides that we support paying with PayPal directly to the host or destination. Currently, PayPal is the only supported provider, but this approach is also applicable to future implementations.

Money is never transferred to our accounts, we only generate payment links with the host or destination as direct target, therefore any payment problems related to the used provider (e.g. PayPal) must be resolved with the receiving party (host etc.) directly. We especially have no option to refund or check any payment related stuff.

You can detect support for online payments in the response of getCategoryDetails in the fields onlinePaymentSupported.

This field is also present in the responses from makeBooking and makeRequestBooking.

If a property is supporting this payment method and the guest is choosing to use it, you can call generatePaymentProviderLink to get a proxy URL for the payment. You will need to supply the booking_no, which step of the payment you want to process (with fresh reservations this should be "initial") and a redirect URI where the customer will be sent back after the payment.

With the response you receive a paymentUri to which you can redirect the user directly or you can use this URI to integrate the dialog directly in your website. There is also a flag present which tells you which provider will be used (can not be chosen).

If the guest fails to make the payment by mistake or any other reason, you can always request a new payment link. However, after the reservation has been done we provide a little login protected area https://www.optimale-praesentation.de/ibe/status where the guest can generate the payment links in self-service. Hosts with Online Payment Support do mention this section in the confirmation email, so you do not need to do this, unless confirmation mails have been suppressed.

Length of Stay (LoS) API

What is LOS API

Length-of-Stay or LOS API format displays the price and availability of a property, for each person, starting from the specified date (startDate) and goes the given number of days in the future (daysInAdvance). For each day and each person the property defined, it shows the cost and availability for the specified number of nights (nights).

Example API response

{
    "2024-07-09": {
        "1": "120,240,360,0,0",
        "2": "130,260,390,0,0"
    },
    "2024-07-10": {
        "1": "120,240,360,0,0",
        "2": "130,260,390,0,0"
    }
}

Request parameters

Parameter Explanation
catNo category id (PriUntNr) of the property
startDate from which date to start calculating the prices, in format Y-m-d. Min value is today.
nights number of nights for every day. Min value is 1, max 50.
daysInAdvance number of days in advance from starting date. Max value is 600.
channelID provided API key

There are also optional parameters:

Examples

To get the LOS prices for a single property send a GET request to /list.php with parameters:
api_path/list.php?catNo=12345&startDate=2021-04-09&nights=40&daysInAdvance=300&channelID=provided-api-key

Rate limits

LOS API has fixed window policy, with allowed 295 requests per minute.

How the final price is calculated for one night

The final price for a single night and person has the following parts:

Example stay:

which would be a total of 285 Euros.

Useful things to know

Webhooks / Push Events

Introduction

The system provides Push Notifications of several types for events in real-time. You can register your Listener to these events. In case of an event the system will call your Listener and send you some details (object no., event type and so on). You will be able to do whatever action you find suitable for the event. In most cases, this will be an update operation, reading the new data using the interface and updating your own database accordingly. All events are sent via a HTTP call to any URL you provide (which must be reachable via the internet, obviously). The called URL will be extended with additional GET key-value pairs. If your URL already contains GET data our data will be appended.

This process was intended to replace the otherwise needed polling of our system by connected services, since there are huge drawbacks in choosing polling over push events. The main argument is the timing. While there are only a few microseconds (plus network latency) between an event and the notification, polling requires you to use a wider timeframe for the single polling events. This can lead to several minutes or even hours delay. Especially in case of occupancy management this is not acceptable and produces a high risk of bookings with no available room. This is why push events for bookings are mandatory for channelmanagers.

Events

Bookings

This event gets fired in case of any new booking, any change to a booking, or any cancellation. It also fires for options and other kinds of reservations. At which point you receive notifications depends on your role. If you are a channelmanager, you will receive all events for your connected objects/units. It is very likely that you will use the provided informations to fetch booking details and update the other connected systems accordingly. If you are a sales channel, you will only get events for bookings you've made yourself via our interface. You can then update your own database and keep track of your bookings.

Occupancy

This event will get fired each time the occupancy gets updated per unit. It is very common to receive a whole bunch of events of this type at (nearly) the same time, for each unit affected by the change. If you are a channelmanager you are not required to listen to this event and it is not very likely that you receive any relevant notifications. This event is mainly designed for sales channels to update their own occupancy table, since they do not receive booking events of sources other than themselves.

Data

This event is in fact a combination of events. It gets fired if any landlord or object data gets changed or updated. This event breaks down to image changes, season/prices changes and simple data changes. This event is solely for sales channels to update their data in real-time, without the need to run a full resync for all objects. You do not need to listen to this event, if you don't want to use real-time updates.

Cancellation Policy (Change)

Cancellation policy events will be fired if your channel is configured for different cancellation policies. This can happen on channel, organisation or landlord level and will result in an event carrying the corresponding keys.

Webhook Example

Your Listener URL

https://myservice.com/listener/doSomething.php?somePara=1

URL we will send a GET request to in case of an event

https://myservice.com/listener/doSomething.php?somePara=1&extraPara=1&extraPara2=1&[...]

Booking Event

This is triggered whenever there is a new or changed reservation, covering the whole lifecycle of a reservation, including cancellation.

Cancellations are just reservations in a different state. They are not handled in a separate way.

Attached GET Parameter

GET Key Value Type
booking_no ID of the booking Integer
keycode access key String
eventtype booking String

Expected Actions

Use the provided data to call getBookingExtendedInfo in Core API. You will notice that the two required values for the function call are what is provided with the event call. You can then read the full booking details using this method.

The access key is generated only once per reservation, so it is a good idea to save it and then use it to fetch updates when needed. However, if you need a huge amount of reservations you are better off with a method capable of bulk requests.

Example

GET https://somewhere.here/some/path/?booking_no=1234567&keycode=d93558b1901031862a75ab6b2a36f04b&object=1234&eventtype=booking&

Occupancy Event

This is triggered per year and per unit for any change in the occupancy.

Attached GET Parameter

GET Key Value Type
catgeory_type privat or gewerblich String
category_no Id Integer
unit_no Id Integer
eventtype bplan String

Expected Actions

Use the interface function getOccupancy to update your data for the submitted category/unit.

Example

GET https://somewhere.here/events/ussop?category_no=1234&category_type=privat&unit_no=1234&object=1234&eventtype=bplan&

Data Event

This is triggered for changes in property data (name, classification, rooms, etc.), property prices/seasons and images. It is pretty much a generic event that any base data has changed.

Attached GET Parameter

GET Key Value Type
catgeory_type privat or gewerblich String
category_no Id Integer
object_no Id Integer
eventtype data or pricesor images String

Expected Actions

Use the event type to determine what has been changed and use the required functions to fetch the changed data (e.g. from getObjectDetails / getCategoryDetails ).

Example

GET https://somewhere.here/events/ussop?category_type=privat&category_no=1234&object_no=1234&object=1234&eventtype=prices&

Cancellation Policy Event

This is triggered for changes in cancellation policies on channel, organisation or landlord level. Notice: This is NOT a reservation cancellation event. This is a data/configuration change. You will only receive this, if you are configured to use different policies.

Attached GET Parameter

GET Key Value Type
override_policy_name the new policy code String
landlord_no Id (optional!) Integer
organisation_no Id (optional!) Integer
eventtype cancellationpolicy String

Expected Actions

Update policy at given level accordingly. Do other updates as needed.

Example

GET https://somewhere.here/events/ussop?override_policy_name=booking_491&landlord_no=1234&organisation_no=1234&eventtype=cancellationpolicy&

Clients

PHP Client

Note that the PHP clients might need additional PHP extensions to be loaded for SOAP and XML support.

PHP Version Downloadlink Status
7.x Download basic connection only
5.6 Download basic connection only

Code Snippets

Here you can find code snippets for some common problems.

Core API getState with WSSE and PasswordDigest

Important: Replace VERSION with the current API version you are using!

POST https://www.optimale-praesentation.de/comm/universal/?v=VERSION HTTP/1.1

Accept-Encoding: gzip,deflate
Content-Type: text/xml;charset=UTF-8

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:USSOP">
    <soapenv:Header>
        <wsse:Security soapenv:mustUnderstand="0"
                       xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
                       xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
            <wsse:UsernameToken wsu:Id="UsernameToken-6A83B9CE21426F733316534947724901">
                <wsse:Username>SOAP_USER_NAME</wsse:Username>
                <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">
                    PUT_PASSWORD_DIGEST_HERE
                </wsse:Password>
                <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">
                    USED_NONCE
                </wsse:Nonce>
                <wsu:Created>2022-05-25T16:06:12.488Z</wsu:Created>
            </wsse:UsernameToken>
        </wsse:Security>
    </soapenv:Header>
    <soapenv:Body>
        <urn:getState>
            <param_getState>
                <category_type/>
            </param_getState>
        </urn:getState>
    </soapenv:Body>
</soapenv:Envelope>

This is an example call of getState with WSSE headers for authentication using PasswordDigest mode.

Core API getObjectDetails call with multiple objects

Important: Replace VERSION with the current API version you are using!

POST https://www.optimale-praesentation.de/comm/universal/?v=VERSION HTTP/1.1

Accept-Encoding: gzip,deflate
Content-Type: text/xml;charset=UTF-8

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:USSOP">
    <soapenv:Header>
        <wsse:Security soapenv:mustUnderstand="0"
                       xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
                       xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
            <wsse:UsernameToken wsu:Id="UsernameToken-6A83B9CE21426F733316534947724901">
                <wsse:Username>SOAP_USER_NAME</wsse:Username>
                <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">
                    PUT_PASSWORD_DIGEST_HERE
                </wsse:Password>
                <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">
                    USED_NONCE
                </wsse:Nonce>
                <wsu:Created>2022-05-25T16:06:12.488Z</wsu:Created>
            </wsse:UsernameToken>
        </wsse:Security>
    </soapenv:Header>
    <soapenv:Body>
        <urn:getObjectDetails>
            <param_getObjectDetails>
                <!--1 or more repetitions:-->
                <object_no>123</object_no>
                <object_no>456</object_no>
            </param_getObjectDetails>
        </urn:getObjectDetails>
    </soapenv:Body>
</soapenv:Envelope>

SOAP Body with native parameters (non-XML content)

Example of Core API cancelBooking (Request Body only)

   <soapenv:Body>
      <urn:cancelBooking>
          <booking_no_cancelBooking>123456</booking_no_cancelBooking>
      </urn:cancelBooking>
   </soapenv:Body>

Some calls only use native SOAP parameter types, especially when the parameter structure is very simple and XML input would be over-the-top. In such cases the values are submitted directly.

PayPal Integration

Notice: This snippet is deprecated by Paypal. The solution is to just open the Paypal Payment URL in the same or another window that will get redirected back to you, just like with the below snippet, but without the previous payment method selection in you website.


<!-- put this in HEAD -->
<script type="application/javascript" src="https://www.paypalobjects.com/webstatic/ppplus/ppplus.min.js"></script>

<!-- place somewhere in BODY (or call after load) -->
<script> var ppp = PAYPAL.apps.PPP({
 'approvalUrl': '___API_GENERATED_URI_GOES_HERE___',
 'placeholder': 'ppplus',
 'mode': 'live',
 'country': 'DE', // modify as needed: user county, will directly influence available payment options!
 'language': 'de_DE', // modify as needed: user language
 'buttonLocation': 'inside',
 'showPuiOnSandbox': true,
 'showLoadingIndicator': false,
 'useraction': 'commit',
 'thirdPartyPaymentMethods': [],
}); </script>
<div id="ppplus" style="width: 100%;"></div>

We support PayPal Payment Link Generation over the API for reservation workflows, if PayPal Support is enabled for the property and host. However, if you want to build a customer facing UI, you might find this code snippet useful for HTML/JS UI.

This code will generate a javascript based payment method selection list, for embedding in your website. After selection has been made the user will be redirected to PayPal. Read the official PayPal Documentation for further explanation. We do not provide support for this snippet.

Changelogs

Core API Changelogs

Version 1.74

Version 1.73

Version 1.72

Version 1.71

Version 1.70

Version 1.69

Version 1.68

Version 1.67

Version 1.66

Version 1.65

Version 1.64

Version 1.63

Version 1.62

Version 1.61

Version 1.60

Version 1.59

Version 1.58

Version 1.57

Version 1.56

Version 1.55

Version 1.54

Version 1.53

This new method returns object rating to view ratings for products or services, including recommendations and feedback. It supports multiple rating aspects (e.g., features, location) and allows responses to reviews.

Version 1.52

Version 1.51

Version 1.50

Version 1.49

This new method returns a tree data structure that can be configured in the back end of the SECRA Destination system.

Version 1.48

Version 1.47

Version 1.46

Version 1.45

Version 1.44

Version 1.43

Version 1.42

Version 1.41

Version 1.40

Version 1.39

Version 1.38

Version 1.37

Version 1.36

Version 1.35

Version 1.34

Version 1.33

Version 1.32

Version 1.31

Version 1.30

Version 1.29

Version 1.28

Version 1.27

Version 1.26

Version 1.25

Version 1.24

Version 1.23

Version 1.22

Version 1.21

Version 1.20

Version 1.19

Version 1.18

Version 1.17

Version 1.16

Version 1.15

This version adds landlord languages, cleaning_fee_included tags and a field for external prices.

Version 1.14

This version adds visitortaxes, md5 hashes for images, and addon counts.

Version 1.13

This version introduces some booking optimizations besides multiple new channelmanager options.

Version 1.12

Version 1.11

You are now able to receive selected request-only objects (this was only supported on a global level before). These objects are included in getState(), but are not online bookable nor available for request booking. You can use sendRequest() to send a request of your guest to the landlord. This request is non-binding. You need to be enabled for this feature to work.

Version 1.10

Version 1.9

Version 1.8

Landlord-Management API Changelogs

Version 1.2

Version 1.1

Version 1.0

Object-Management API Changelogs

Version 1.6

Version 1.5

Version 1.4

Version 1.3

Version 1.2

Version 1.1

Version 1.0

Errors

See Error Handling for more details.

Error Code List

Code Message
0 success
1 login failed - missing or empty parameter
2 login failed - wrong credentials or not authorized
3 login required
4 parameter missing or invalid
5 unspecified query error
6 no matching record found
7 object found, but missing configuration
8 arrival date invalid
9 departure date invalid
10 arrival and departure date invalid
11 too less days before arrival
12 travel dates not accepted
14 no direct booking enabled, requires (human) request
15 partly or complete missing date ranges configuration
16 too many adults
17 too many children
18 too many people
19 not available / in use
20 maximum price exceeded
21 departure before arrival
22 arrival in the past
23 action failed
24 missing value: anrede
25 missing value: land
26 missing value: email
27 from-value is in the past
28 there are undefined periods within given ranges
29 overlaping date ranges
30 incorrect authcode
31 too many requests, flooding detected - you should not encounter this error if you are using this service in the right way. contact technical support if required.
32 you logged in too many times without performing any action, please check your implementation and avoid pointless traffic (this is a temporary error)
33 the requested object does not support this type of action
34 invalid addon specified, code was not listed in current addons (try calling getBookingParameter again or check your code)
35 age ranges do not match (and there are age restrictions in effect for this object)
36 range too long, exceeded maximum duration
37 invalid value for field: catering
38 access denied: insufficient rights
39 url invalid
40 from and until date are identical, please specify at least one night
41 tried to book more units of an addon than available
42 the answer to life, the universe and everything
43 you can not make a booking for literally nobody, please submit a valid person count
44 external price is not the same as the calculated booking price, please submit a value higher or even
45 unable to calculate price, check parameters for logical errors
46 input format invalid, validate your code against the xsd
47 catering option invalid
48 no record found for given booking_no or reservation not done by you
49 payment option is not supported for this object
50 missing or invalid redirect URIs
51 no payment required
52 payment flow step is unrecognized
53 payment link could not be retrieved from provider, possible config error
54 rrv data is already added
55 value for field email failed validation (invalid domain or not cappable of mail transfer due to missing A and MX DNS records), either this mail is fake or a typo
56 missing parameter booking_no
57 operation not permitted on this reservation
58 specified cancellation fee is not valid/accepted
59 cancellation fee amount is not valid
60 maximum available addon amount can not be lower than 1, set addon to unavailable instead, rule partially ignored
61 extra traveller data has errors
62 season start is identical to end date
63 there is a gap in an addonbeds price definition (make sure to leave no price definition gaps or fill gaps with explicit definitions even if step price is zero)
64 there is a syntax error in your submitted request, check your request against the embedded XSD in the WSDL spec
65 addon bed definitions must not overlap with base occupancy
66 margin has to be a positiv integer or float value
67 invalid value for field: cleaning_fee_place_of_payment
68 invalid value for field: deposit_place_of_payment
69 invalid value for field: external_id
70 payment provider is not supported
71 payment provider is not available for host
80 Discount id is not valid.
81 Discount for this id not found.
82 Invalid value for discounted amount.
83 Discount not applicable.
101 property id not found in the objects organisation
102 holiday_theme id not found in the objects organisation
103 distance id not found in the objects organisation
104 to age lower then from age
105 the number of adults is higher than the number of overall persons
106 required parameter not found in persons element
107 more age ranges than persons
110 object is missing the minimum required data, see docs for details
111 the landlord_no provided, is invalid
112 the country given is invalid
113 the type given is invalid
114 the location given is invalid
115 the geolocation given is invalid
116 the visitor tax place of payment given is invalid
120 object_no not found
130 from date is invalid
131 until date is invalid
132 from value is too far in the past
133 until value is too far in the past
134 room type is invalid
200 landlord creation is not enabled for this account and/or on this organisation
201 landlord is not accessible or non existent
202 you can only modify landlords you have created (using this api)
203 your current account status is not valid for this type of action
204 formal error, content validation failed on some fields: iban
205 landlord is missing the minimum required data, see docs for details
206 provided landlord_no and landlord of the provided object_no do not match
207 provided landlordbilling_language is not supported
1000 quota reached: max landlords
1001 quota reached: max objects
1002 quota reached: max images per object
1003 quota reached: max objects per landlord

FAQ

This is a collection of commonly asked questions and their answers.

I receive a "parameter missing or invalid" error without further details. What does that mean?

In general there are two possible reasons:

The provided WSDL file contains an embedded XSD specification. We highly suggest validating your request against it as it will point to the most common errors. If you are using some kind of testing software (e.g. SoapUI) there is a good chance there is already a feature for this.

I have received a success response, but my data isn't showing up. Why?

The success response only indicates that the server has processed your response without an error, it does not mean that your request was without logical/content errors. Especially errors related to the content you submit are not detectable to the server.

Other reasons are that if you violate the XSD for example, invalid/misplaced parts of your request might have been cut, so the success response only says there was no error in the valid part (if any).

If you look for an error, the first step is as always to validate your request against the embedded XSD in the WSDL file. This will cover like 90% of typical errors.

I receive responses with HTTP status 429, what does that mean?

You are blocked by the Rate Limiting. More details here.

Can you raise the Rate Limit for me?

No. Rate Limits are specified globally and can not be adjusted per user.

The API stopped working after a new version was deployed. What can I do?

We are running a versioned API, that means you can use older versions with unchanged interfaces. It also means that you must pin your usage to a specific version (as mentioned in the docs), otherwise you will always use the latest version with the possibility of breaking changes. If you encounter this error because you are running on "latest", pin the version in the WSDL or endpoint URL (depending on what you are using). This is as simple as just adding the missing GET parameter v to the URL and set a version explicitly. Just pin to the last kown working version and you have this fixed within under 10 keystrokes. See Versioning section.

Where do I get XML sample requests?

You can use the WSDL file with the embedded XSD to generate your own XML samples with many SOAP tools like for example SoapUI.

For SoapUI just open a new project and load our WSDL file, then mark the checkbox to generate samples (link).

soapui_dialog

Since our API is versioned and updated frequently this is a lot more useful than any static (and maybe outdated) samples in the documentation could ever be, since the WSDL file is using the exact same version as you.

Help

We are here to help! Contact us!

contact-photo

Asmus Jacobsen
Partner Success Manager

partner@secra.de

Before you write or call us

Please answer these questions before reaching out to us. It makes our support process a lot faster, as we will otherwise most likely need to ask you these questions anyway at a later stage.