Manawa API integration for suppliers (1.0)

Download OpenAPI specification:Download

API integration contact: tech@manawa.com

Overview

This document describes the standards used to establish connectivity between a supplier’s system (typically BMS / SRS platforms, Channel Managers) and Manawa.com.

To achieve this connectivity, the supplier must provide an API consisting of endpoints that allow Manawa to query the availability of products, place reservations and bookings, as well as cancel them. All of these supplier-side endpoints must be implemented for a successful integration.

Operating principles

Manawa will send requests to URLs described in the document, passing parameters and data as specified and expecting data to be returned as specified.

For example, when we need to retrieve availability for a given product, we will call https://your-host.com/1/get-availabilities. Your endpoint must return availability data in a format that complies with the spec. This data will then be used by Manawa to obtain product availabilites, pricing rules, and to display a booking interface to the users.

The workflow that we use is very simple:

  1. When a Manawa customer wish to check availability for an activity, we send a /get-availabilities request with date ranges, to your API. With the returned info, we can display a booking interface to the customer.

  2. When the customer decides to add the activity to its shopping cart, we call /reserve in order to secure the slots in the inventory for a limited time period.

  3. When the customer confirms and pays, we call /book to confirm the booking.

  4. [Coming soon] If cancellation is necessary, we call /cancel-booking.

Also note that:

  • The API does not cover static data such as product descriptions, policies or pictures. Static data is managed by the Manawa Sales & Integration team.

  • Mapping between your products and Manawa products is done by Manawa. We ask you to implement a few, simple endpoints to facilitate mapping.

  • Payment from customers and commission payouts to suppliers are handled by Manawa.

API format

The API must be implemented as a set of regular HTTPS endpoints that handle data as JSON formatted payloads as per specifications. It is important that the HTTP Content-type header is set to application/json for all responses.

Please note as well that we always expect a 200 HTTP status code, as long as the response contains an expected payload (this includes error codes). All non 200 HTTP status codes are considered transport and/or server failures. See Error handling section for more info.

Please also note that we might add additional non-breaking fields to each data structure at our convenience; your JSON deserializer should be flexible enough to handle these new fields without breaking. API changes are described in the Changelog section.

Consider as well that Manawa is localized in several languages. It’s mandatory for your API to support UTF-8 character encoding both in requests and responses.

Requests will use GET or POST. Request data for GET requests will be passed as query string. Data for POST requests will be passed in the request body as JSON.

You can use any domain, subdomain, or subdirectory as base (https://your-host.com, https://api.your-host.com, https://your-host.com/api/ are all valid).

The API is versionned to ensure backwards compatibility. All endpoints must be prefixed with the API major version number (currently: /1/). E.g: https://your-host.com/1/get-availabilities.

Authentication

Your endpoints must be secured using HTTP Basic Auth. We will pass an Authorization HTTP header in each request.

# [token] is the base64-encoding of `[username]:[password]`
Authorization: Basic [token]

Username and password are managed by the Supplier platform. Any string is accepted (email, username, API token...).

Please not that only Basic authentication is accepted. No other forms of authentication are allowed (e.g OAuth or Bearer token).

Performance

Our client is configured with a 30 seconds timeout limit. All responses taking longer will be ignored and the request will fail.

However, we strongly advise that responses should not take longer than 10s, in order to provide a satifying customer experience.

Error handling

When an error occurs, it should be categorized into one of the types listed in the table below in order to facilitate automatic responses to errors, error handling and debugging.

Please note, the error structure must be present in the response only if the request is not successful. The API response will accept either the data structure with the successful response or the errorCode structure, not both. Inconsistency might lead to the API requests to fail.

Errors applicable to all endpoints

Error Code                      Explanation
AUTHORIZATION_FAILURE The provided credentials are not valid.
{
  "errorCode": "AUTHORIZATION_FAILURE",
  "errorMessage": "The provided authentication credentials are not valid."
}
INVALID_PRODUCT The specified product does not exist or is broken for another reason (excluding availability issues).
{
  "errorCode": "INVALID_PRODUCT",
  "errorMessage": "This activity should be deactivated; not sellable."
}
VALIDATION_FAILURE The request object contains inconsistent or invalid data or is missing data, such as incorrect date range requested, timeslots are in the past, etc. Please provide as much detail as possible in the error message.
{
    "errorCode": "VALIDATION_FAILURE",
    "errorMessage": "The requested travel date is in the past."
}
INTERNAL_SYSTEM_FAILURE An error occurred that is unexpected and/or doesn’t fit any of the types above, including timeouts, service not reachable, etc. Please provide as much detail as possible in the error message.
{
  "errorCode": "INTERNAL_SYSTEM_FAILURE",
  "errorMessage": "A timeout has occured. The request exceeded 10 seconds."
}

Errors applicable to specific endpoints

Error Code                      Explanation
NO_AVAILABILITY Applicable endpoint: Reservation, Booking
The reservation or booking call cannot be fulfilled because there is insufficient availability.
{
    "errorCode": "NO_AVAILABILITY",
    "errorMessage": "This activity is sold out; requested 3; available 0."
}
INVALID_TICKET_CATEGORY Applicable endpoint: Reservation, Booking
The reservation or booking call specified a ticket category that is not configured for the requested product.
{
    "errorCode": "INVALID_TICKET_CATEGORY",
    "errorMessage": "The ticket category youth is not sellable.",
    "ticketCategory": "YOUTH"
}
ticketCategory must match a ticket category supported. The value for this field should be the (or one of the) unexpected ticket categories that have been requested.
INVALID_PARTICIPANTS_CONFIGURATION Applicable endpoint: Reservation, Booking
The reservation or booking call specified a ticket quantity that is not allowed for the requested product. This is based on the minimum or maximum number of participants per booking that have been configured for this product in your system.

Individual Ticket Categories
For Individual ticket categories, which consists of all ticket categories except Group, the expected response is:
{
    "errorCode": "INVALID_PARTICIPANTS_CONFIGURATION",
    "errorMessage": "The activity requires a minimum of 4 participants.",
    "participantsConfiguration": {
      "min": 4,
      "max": 10
    }
}
In this example we might have made a request for two Adult tickets. This did not meet the product’s minimum participant number (four) in your system, so we received this error response.

Group Ticket Category
If you are returning an error to a booking request for a Group ticket, you must include the groupConfiguration structure:

{
  "errorCode": "INVALID_PARTICIPANTS_CONFIGURATION",
  "errorMessage": "The activity can only be booked for 1 group.",
  "participantsConfiguration": {
    "min": 1,
    "max": 20
  },
  "groupConfiguration": {
    "max": 1
  }
}

The groupConfiguration structure with the element max (Integer, at least 1) specifies how many Group tickets can be booked for each timeslot.

You only need to include the groupConfiguration structure if you are returning an error on a booking request for a Group ticket. For all Individual ticket categories this structure should be omitted.

INVALID_RESERVATION Applicable endpoint: Booking
The booking call cannot be fulfilled because specified reservation does not exist or is not in a valid state.
{
    "errorCode": "INVALID_RESERVATION",
    "errorMessage": "Expired reservation; 60min hold time was exceeded."
}
INVALID_BOOKING Applicable endpoint: Booking Cancellation
The booking cancellation call cannot be fulfilled because booking does not exist or is not in a valid state.
{
    "errorCode": "INVALID_BOOKING",
    "errorMessage": "The booking has been cancelled already."
}
INVALID_SUPPLIER Applicable endpoint: Get Products List
The request is not valid because the supplier does not exist or is not configured to sell on Manawa.
{
    "errorCode": "INVALID_SUPPLIER",
    "errorMessage": "Supplier does not exist in the system."
}

General Definitions

Datetime formats

Points in time are expressed as strings using the ISO 8601 datetime format (e.g. 2020-12-05T14:00:00+02:00). We always expect the local time with its timezone as UTC offset.

Example: Dog sledding tour in Montreal, 5th of December 2020 at 14:00 (local time):

Expected: 2020-12-05T14:00:00-05:00

Not expected: 2020-12-05T21:00:00+02:00 / 2020-12-05T19:00:00+00:00

Please note that although the above examples express the same point in time, we consider only the first one valid as we always require the date and time in reference to the location of the activity.

Ticket categories

Please find the list of the supported ticket categories below. All categories describe an individual with the exception of GROUP.

Complete list of supported categories:

  • ADULT
  • CHILD
  • YOUTH
  • INFANT
  • GROUP

The GROUP category should be used for products using a Group pricing strategy (typically when the base stock unit can accomodate several passengers).

Individual pricing vs Group pricing

Consider a supplier that provides Quad Biking tours. Each Quad bike can accomodate 1 or 2 passengers. We want to place an order for 2 ADULT and 1 YOUTH.

If the supplier decides to apply individual pricing:

  • Each person riding will have an individual ticket.
  • Prices must be returned using ADULT and YOUTH categories
  • Upon booking we will order 2 ADULT + 1 YOUTH.
  • We expect you to respond with 3 tickets, 2 of type ADULT and 1 of type YOUTH.

If the supplier decides to apply group pricing:

  • There will be 1 ticket per quad bike, no matter the number of pax riding it.
  • Prices must be returned using GROUP category
  • Upon booking we will order 2 GROUP tickets (to accomodate the 3 pax).
  • We expect you to respond with 2 GROUPtickets.

Product ID

The ID of the requested product in the supplier’s system. Each product ID maps to one Activity Variant on Manawa. An Activity Variant can have multiple starting times, but a single product ID needs to respond to all of them. It can be up to 255 characters long.

Please refrain from using the character % in your Product ID, as it is used as an escape character during URL encoding. The use of % may lead to failed encoding of the product ID in the URL.

Please note that we will not map individual time slots, different languages and different ticket categories but you can encode all this information into the product ID (e.g. via a JSON structure) as long as you provide a string of maximum 255 characters long.

Availability

Availability Query

This endpoint must return availability and pricing information for a given product, during a date range specified in the request parameters.

The response must contain the availability for each time slot of the requested product that falls within the supplied time period. We may send requests asking for up to 31 days of availabilities, for dates up to 13 months in advance.

Call frequency

In order to get real-time availability, Manawa will call this endpoint whenever a Manawa customer requests availability for a connected activity. To avoid excessive load, availability responses are cached for 15 minutes.

No availability response

If there is no availability for a timeslot that falls within the range, you must return an entry with 0 availability e.g. vacancies: 0. Please do not return a NO_AVAILABILITY error code.

If there is no availability at all in the given time range we expect an empty array. NO_AVAILABILITY must be used while handling a request for /book only.

Availability for groups

Please note, for GROUP products the vacancies field should contain the total number of available groups, not the total number of individual vacancies.

For example, if you accept a maximum of 10 groups per timeslot you should return vacancies: 10.

More details about group pricing here.

Time Point products vs. Time Period products

  • Time point products are activities that start at a precise time (eg, boat tours). People book for a specific date and time slot.

  • Time period products are activites with no pricise starting time, either because:

    • Start time varies (eg, tides)
    • Start time is not known well in advance and must be arranged at the last minute (eg, weather-dependent activities such as paragliding)
    • Client can come any time (eg, self-guided activities such as canopy tours)

Time point

  • You can send us as many time points for an activity for a given day as you conduct it.
  • The availability response must indicate the exact time when the participant is expected to check-in.
  • The DateTime format is expected to contain the complete date and time information.
"availabilities": [
  {
    "dateTime": "2020-12-01T10:00:00+02:00",
    // ...
  },
  {
    "dateTime": "2020-12-01T15:00:00+02:00",
    // ...
  }
]

Time period

  • You may only send us 1 occurrence per any given day.
  • The DateTime format is expected to contain the date information and the time to be set to 00:00:00, for example: 2020-12-05T00:00:00+04:00.
  • You may optionally provide us the opening hours (openingTimes). Opening times spanning the full day can be expressed by setting fromTime to 00:00 and toTime to 23:59. Any availability containing 24:00 in the opening times definition will be ignored by our system.
"availabilities": [
  {
    "dateTime": "2020-12-01T00:00:00+02:00",
    // ...
    "openingTimes": [
      {
        "fromTime": "09:00",
        "toTime": "12:00"
      }
    ],
  },
  {
    "dateTime": "2020-12-02T00:00:00+02:00",
    // ...
    "openingTimes": [
      {
        "fromTime": "09:00",
        "toTime": "18:00"
      }
    ],
  }
]

Cutoff period

The optional field cutoffSeconds is an integer representing the cut-off time in seconds. The cut-off needs to be sent on the starting time/opening hours level. If unspecified, we will use a default cut-off value defined by Manawa (72 hrs).

For example: An activity has two starting times on May 10th: 11:00 and 13:00. The cut-off may be sent for both timeslots or only for the starting time 11:00. In this scenario the 13:00 timeslot will use the default cut-off configured by Manawa.

Please note that the cut-off can not be negative.

Price

All fields (currency and pricesByCategory) and nested subfields (retailPrices - an array of objects containing category and price) are required.

The price for each category (Adult, Child, etc) must be present for each datetime received in your response. If a category and relevant price is absent, the response will be deemed invalid.

We make calls for availability upto 365 days in the future, so please ensure these are present in your system and your responses. If pricing data is absent, the response will be deemed invalid and the affected datetimes will become unbookable.

Similarly, price shared for GROUP category should apply to the whole group, regardless of its size.

Optional module: Tiered Prices

If your system supports Tiered Prices, your can return the optional tieredPricesByCategory field in your availability response.

If tieredPricesByCategory is provided, Manawa will consume the tiered prices and ignore values defined in pricesByCategory. If tieredPricesByCategory is not defined, Manawa will fallback to using pricesByCategory.

Example

Adult Child
1-3 pax EUR 50 EUR 30
4-10 pax EUR 45 EUR 25
10+ pax EUR 40 EUR 20

In the example, a person booking for 4 adults and 2 children would have to pay 45 EUR per adult and 30 EUR per child (total EUR 240).

The corresponding tieredPricesByCategory value would need to be:

{
  "retailPrices": [
    {
      "category": "ADULT",
      "tiers": [
        {
          "lowerBound": 1,
          "upperBound": 3,
          "price": 5000
        },
        {
          "lowerBound": 4,
          "upperBound": 10,
          "price": 4500
        },
        {
          "lowerBound": 11,
          "upperBound": 200,
          "price": 4000
        }
      ]
    },
    {
      "category": "CHILD",
      "tiers": [
        {
          "lowerBound": 1,
          "upperBound": 3,
          "price": 3000
        },
        {
          "lowerBound": 4,
          "upperBound": 10,
          "price": 2500
        },
        {
          "lowerBound": 11,
          "upperBound": 200,
          "price": 2000
        }
      ]
    }
  ]
}
Authorizations:
BasicAuth
query Parameters
productId
required
string
Example: productId=prod123

The ID of the requested product in the supplier’s system. Please avoid using the character % in the productId, as it is used as an escape character in URL encoding and may cause encoding/decoding failures in query parameters.

fromDateTime
required
string
Example: fromDateTime=2020-12-01T00:00:00+02:00

Marks the start (inclusive) of the requested time period (ISO 8601).

toDateTime
required
string
Example: toDateTime=2020-12-01T23:59:59+02:00

Marks the end (inclusive) of the requested time period (ISO 8601).

Responses

Response samples

Content type
application/json
Example
{
  • "data": {
    }
}

Reservations

Reservation

This call is made when customers add an activity to their cart. It represents the first step of the booking process. It must reserve the requested quantities in the supplier’s system for at least 1 hour in order to guarantee a successful booking within the following hour. Failure to do so will potentially result in unconfirmed bookings if the product is no longer available.

Please note that we allow customers to add a product to the cart through the reserve endpoint until the time specified by the cut-off of the product (see Cutoff over API under the Availability Query).

This feature is not yet fully implemented by Manawa. At the moment, /reserve and /bookrequests are chained together and sent when customers confirm their purchase. In other words, when a customer pays, we "reserve" the booking and send a "book" request immediately after.

We will soon move the call to /reserve when adding to the cart, and use the proper reservation process explained above. So we strongly advice to support it right now in your API.

Authorizations:
BasicAuth
Request Body schema: application/json
required
object

Responses

Request samples

Content type
application/json
Example
{
  • "data": {
    }
}

Response samples

Content type
application/json
Example
{
  • "data": {
    }
}

Reservation Cancellation

This call represents when either the customer removes the item from their shopping cart, or when it’s automatically removed by default after 1 hour. When called, Quantities reserved during the call to /reserve should be released by the Suppliers' system.

This feature is not yet used by Manawa. At the moment, /reserve and /book requests are chained and sent when customers confirm their purchase. In other words, when a customer pays, we "reserve" the booking and send a "book" request immediately after.

This means that reservations are never cancelled by Manawa at the moment.

We will soon use the proper reservation process as described in the /reserve endpoint, so we strongly advice to support it right now in your API.

Authorizations:
BasicAuth
Request Body schema: application/json
required
object

Responses

Request samples

Content type
application/json
{
  • "data": {
    }
}

Response samples

Content type
application/json
{
  • "data": { }
}

Bookings

Booking

This call confirms a reservation that has been placed previously and provides additional information.

Whenever a call to this method previously failed, it will be retried up to 10 additional times. In case the booking was confirmed internally on the supplier’s side, this endpoint must return the expected response (repeat booking confirmation) without generating another booking nor an error.

Authorizations:
BasicAuth
Request Body schema: application/json
object

Responses

Request samples

Content type
application/json
{
  • "data": {
    }
}

Response samples

Content type
application/json
Example
{
  • "data": {
    }
}

Booking Cancellation

This call must cancel the booking in your system.

This feature is not yet used by Manawa, but will be implemented soon, so we strongly advise to support this endpoint right now.

In the meantime, cancellation notifications are sent by email to the supplier by Manawa Customer Services. Supplier is then responsible for manually cancelling the booking in its Booking Platform.

Authorizations:
BasicAuth
Request Body schema: application/json
required
object

Responses

Request samples

Content type
application/json
{
  • "data": {
    }
}

Response samples

Content type
application/json
{
  • "data": { }
}

Products

Suppliers List

The Supplier List endpoint allows Manawa to query a list of supplier available through the API. The generated list will enable mapping of products between the Connectivity Partner and Manawa.

Supplier List Endpoint

The endpoint returns the entire list of suppliers as response.

Authorizations:
BasicAuth

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Products List

The Product List endpoint allows Manawa to query a list of supplier products programmatically. The generated product list will enable mapping of products between the Connectivity Partner and Manawa.

Product List Endpoint

The endpoint returns the entire list of products as response for a requested supplier ID.

Authorizations:
BasicAuth
path Parameters
supplierId
required
string
Example: Abc123

The ID of the supplier on the Connectivity partner's system.

Responses

Response samples

Content type
application/json
Example
{
  • "data": {
    }
}

Product Details

This endpoint returns a set of content and configurational settings for a product based on a requested product ID (ID of the product on the Connectivity partner's system)

Authorizations:
BasicAuth
path Parameters
productId
required
string
Example: PPYM1U

Product identifier in the Connectivity partner's system

Responses

Response samples

Content type
application/json
Example
{
  • "data": {
    }
}

Pricing Categories

The categories over API endpoint allows Manawa to import the price category data for a given product.

Only supported categories would be accepted and consumed. Any non supported category received via the endpoint would be rejected

Authorizations:
BasicAuth
path Parameters
productId
required
string
Example: prod123

The ID of the requested product in the supplier’s system.

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Changelog

Date Version Notes
2024-12-26 1.0.0 Initial release
2025-06-24 1.1.0 Add Suppliers List endpoint