ParkingsAdmin API for channels

(Revised 2019-11-19)

Introduction

Parkingsadmin.com is a SaaS for parkings that manages parking bookings and integrates all the booking channels of a parking in one place. It helps managing the availability, checkin, reporting and invoicing.

This API is ready for the distribution channels that sell bookings in the name of the parking. Every parking activates a channel in our system to distribute the product and then the Channel is authorized to make reservations through this system.

Format and Versioning

This API is a REST API that speaks JSON. It will always return JSON (unless otherwise stated) and it assumes that information is sent as JSON BODY when possible, besides the query string parameters, of course.

You should include an Accept header including the accepted content type and the version like this:

Accept: application/json;

You should also include a Content-Type header informing about the content type of your request like this:

Content-Type: application/json

You should include an Accept-Language header including the language code (en, es fr) to get errors in the specified language, like this:

Accept-Language: en;

Identification and Authentication

All request must include a User-Agent information including the plattform and (separated by a space) the client version (not the OS version) that is making the request, for instance:

User-Agent: "channels/channel.com 1.0.1"

You will be provider with the left part of the user agent by us.

Most entry points require authentication. To authenticate your request you must use the "Authorization" HTTP header using as value the token provided by us to every channel and prefixing it with the string "Bearer "

Authorization: "Bearer 22ca8686bfa31a2ae5f55a7f60009e14"

Errors

The API returns errors using the standard HTTP response codes (see http://www.restapitutorial.com/httpstatuscodes.html). The error also has a JSON response including the code and a message.

Servers

You can use our test server as sandbox with another token that will be provided to you.

The following table shows the location of each endpoint:

Server URL
Test (Sandbox) https://api-sandbox.parkingsadmin.com
Production https://api.parkingsadmin.com

Entities summary

Entity Verb Auth Action
/parkings GET Channel Get the list of parkings
/bookings POST Channel Create a new Booking
/bookings/{id} PUT Channel Modify a Booking
/bookings/{id} DELETE Channel Cancel a Booking
/bookings-available GET Channel Check availability and price

Booking process

BEFORE creating a booking, the channel SHOULD check the availability for that parking and dates. If you try to create a booking and there is no availability you will get a 409 error anyways.

1) GET /parkings to know our parking ID for the parking that you have permissions. 2) GET /bookings-available to check availability (and price) for specific dates. 3) POST /bookings to create the booking. 4) PUT /bookings/{id} to modify a booking. 5) DELETE /bookings/{id} to cancel a booking.

Parkings Collection [/parkings]

This collection only accepts GET verb from a Channel to request the list of authorized parkings to distribute and their IDs which you will need in the POST /bookings phase.

List Parkings [GET]

This request does not accept any parameters.

Fields

  • id: Integer number that represents the parking in all our API endpoints.

  • name: String with the name of the parking.

  • country: Object containing the ISO 3166-1 alpha-2 code and the local representation of the name.

  • timezone: String. Must be in the list of tz database time zones.

  • currency: String, 3 chars capital letters. Following ISO 4217 standard.

  • vat_percentage: Float, percentage of VAT or equivalent tax, can have up to 2 decimal positions.

  • margin: Float. The margin field will show the default margin for that parking. If your agreement has variable margins, don't worry, you can overwrite this on every booking. The margin is represented as a float of the percentage (without the % symbol). For instance, if margin is a 20.5%, the representation will be 20.5.

  • required_fields: Array of strings. When sending a booking for this parking you must add those fields as required. Can have up to 2 decimal positions.

  • Response 200 (application/json)

{
  "data":
  [
      {
        "id": 1,
        "name": "Example Parking in Madrid",
        "country": {
          "code": "ES",
          "name": "España"
        },
        "timezone": "Europe/Madrid",
        "currency": "EUR",
        "vat_percentage": 21,
        "margin": 20,
        "required_fields": [
            "vehicle_plate"
        ]
      },
      {
        "id": 2,
        "parkingName": "Example Parking in Rome",
        "country": {
          "code": "IT",
          "name": "Italia"
        },
        "timezone": "Europe/Rome",
        "currency": "EUR",
        "vat_percentage": 22,
        "margin": 22.25,
        "required_fields": []
      }
  ]
}

Bookings available Collection [/bookings-available]

Be careful with timezones and DTS changing dates because sometimes a booking from 8AM today to 8AM tomorrow can be a 23, 24 or 25 hours booking and most parkings calculate their rates using 24-hour schemas. The dates and times must be in the timezone of the parking.

The response will be an array including a json object for each requested parking (given that the parking id exists and the channel has permissions to access it). If the available attribute is true, then there is availability for a booking.

If the price attribute is not null it means that the parking has dynamic price and that is the price you must charge the user. If the price is null, you should use the rates provided by the parking in advance.

The product_code and product_name are the code and name of the product (or rate), so you can store it in your database. They can be null.

The array required_fields in the /parkings request will show if any of the optional fields are required for this parking.

  • Parameters
    • parking_id (integer) - REQUIRED ID of the Parking. You can pass several IDs separated by comma.
    • arrival_date (ISO 8601 date YYYY-MM-DD) - REQUIRED Date of arrival (at parking timezone), f.i. 2021-12-28. The system won't admit bookings more than 365 days in advance. This date should not be in the past.
    • arrival_time (ISO 8601 time hh:mm ) - REQUIRED Hour of arrival in 24 hours format (at parking timezone), f.i. 07:00 for 7AM. The date and time should not be in the past.
    • departure_date (ISO 8601 date YYYY-MM-DD) - REQUIRED Date of departure (at parking timezone), f.i. 2021-12-31. The system won't admit bookings of more than 31 days or less than 1 hour.
    • departure_time (ISO 8601 time hh:mm ) - REQUIRED Hour of departure in 24 hours format (at parking timezone), f.i. 18:00 for 6PM.

Check availability [GET]

  • Response 200 (application/json)

Single parking:

{
    "availability": [
      {
        "parking_id": 1,  
        "available": true,
        "price": 19.30,
        "product_code": "20SU01D",
        "product_name": "1 day"
      }
    ]
}

Several parkings:

{
    "availability": [
      {
        "parking_id": 1,  
        "available": true,
        "price": 19.30,
        "product_code": "20SU01D",
        "product_name": "1 day"
      },
      {
        "parking_id": 2,  
        "available": false,
        "price": null,
        "product_code": null,
        "product_name": null
      }
    ]
}

Bookings Collection [/bookings]

Create a New Booking [POST]

Possible HTTP status codes:

Code Description
201 Created (OK!)
400 Bad request, f.i. wrong phone number, missing field, etc
401 Unauthorized, f.i. No channel token was provided
403 Forbidden, f.i. Channel has no permission for parking
404 Not found, f.i. Parking not found
409 Conflict, f.i. No places available, duplicated booking...
  • REQUIRED Parameters

    • parking_id (string) - ID of the Parking (check /parkings if you don't know it).
    • booking_code (string) - REQUIRED The channel's booking ID. Can be letters and numbers up to 128 characters.It is recommended to be less than 16 characters
    • vehicle_type (string) - REQUIRED car|van|motorcycle (other types can be added in the future)
    • price (float) - REQUIRED Total price including taxes.
    • prepaid (boolean) - true if the booking has already been paid, note that most parkings only allow prepaid reservations. OPTIONAL: True by default.
    • arrival_date (ISO 8601 date YYYY-MM-DD) - Date of arrival (at parking timezone), f.i. 2021-12-28.
    • arrival_time (ISO 8601 time hh:mm ) - Hour of arrival in 24 hours format (at parking timezone), f.i. 07:00 for 7AM.
    • departure_date (ISO 8601 date YYYY-MM-DD) - Date of departure (at parking timezone), f.i. 2021-12-31.
    • departure_time (ISO 8601 time hh:mm) - Hour of departure in 24 hours format (at parking timezone), f.i. 18:00 for 6PM.
  • MAYBE REQUIRED by some parkings (check /parkings to know the required fields)

    • customer_email (string) - Driver email, please check the syntax before sending.
    • customer_name (string) - Name and surname of the driver as he/she wants to be addressed.
    • customer_phone (string) - Driver phone. With international prefix and no spaces (f.i. +34999888777)
    • vehicle_plate (string) the license plate of the vehicle, no spaces (f.i. 8744FFH).
    • vehicle_model (string) the brand and model of vehicle (f.i. BMW x5).
    • vehicle_color (string) the main color of the vehicle, in the parking language or English (f.i. Blue).
    • transportation_passengers (integer) must be a dropdown with options from 1 to 8, numbers.
    • transportation_departure_time and transportation_arrival_time (time) must be a hour in this format: 23:59. You must check to this regexp ^(:?[0-1][0-9]|2[0-3]):[0-5][0-9]$ or (recommended) just show the user a dropdown with all hours in the day with 15 minutes intervals.
    • transportation_departure_terminal and transportation_arrival_terminal (string) is RECOMMENDED to match with this regexp: ^[a-zA-Z0-9._%+-]{1,255}$.
    • transportation_departure_number and transportation_arrival_number (string) are the flight numbers or vessel names. For flights, it is RECOMMENDED to match with this regexp: ^[A-Z0-9]{1,8}$.
  • OPTIONAL fields

    • margin (float) - Margin percentage for the channel. Maximun 2 decimals. OPTIONAL: the default margin defined by the parking will be used if none is set.
    • customer_language_code (string) - specify the language, use the ISO 639-1 two letter code that applies in the standard (lowercase).
    • customer_country_code (string) - Two-letter (uppercase) country code defined in ISO 3166-1.
    • special_requests (string).
  • Minimum Request (application/json)

{
  "parking_id": "2",
  "booking_code": "123456",
  "price": 19.55,
  "arrival_date": "2021-12-29",
  "arrival_time": "10:00",
  "departure_date": "2021-12-30",
  "departure_time": "10:00",
  "customer_name": "John Doe",
  "customer_phone": "+34999888777",
  "vehicle_type": "car"
}
  • Request (application/json)
{
  "parking_id": "2",
  "booking_code": "A23EF61234",
  "price": 19.55,
  "prepaid": true,
  "arrival_date": "2021-12-29",
  "arrival_time": "10:00",
  "departure_date": "2021-12-30",
  "departure_time": "10:00",
  "customer_name": "John Doe",
  "customer_phone": "+34999888777",
  "customer_email": "[email protected]",
  "customer_language_code": "es",
  "customer_country_code": "ES",
  "transportation_passengers": 4,
  "vehicle_type": "car",
  "vehicle_plate": "0000EEE",
  "vehicle_model": "Audi Q3",
  "vehicle_color": "White",
  "transportation_departure_time": "13:00",
  "transportation_departure_terminal": "2",
  "transportation_departure_number": "IB8876",
  "transportation_arrival_time": "16:00",
  "transportation_arrival_terminal": "2",
  "transportation_arrival_number": "IB8867",
  "special_requests": "One of the passengers is a RMP."
}
  • Response 201 (application/json)
{
  "id": "6542",
  "booking_code": "A23EF61234",
  "parking_id": "2",
  "created_at": "2020-12-28 19:00:00",
  "arrival_at": "2020-12-29 19:00:00",
  "departure_at": "2020-12-23 19:00:00",
  "canceled_at": null,
  "price": 19.55,
  "prepaid": true,
  "arrival_date": "2021-12-29",
  "arrival_time": "10:00",
  "departure_date": "2021-12-29",
  "departure_time": "10:00",
  "customer_name": "John Doe",
  "customer_phone": "+34999888777",
  "customer_email": "[email protected]",
  "customer_language_code": "es",
  "customer_country_code": "ES",
  "transportation_passengers": 4,
  "vehicle_type": "car",
  "vehicle_plate": "0000EEE",
  "vehicle_model": "Audi Q3",
  "vehicle_color": "White",
  "transportation_departure_time": "13:00",
  "transportation_departure_terminal": "2",
  "transportation_departure_number": "IB8876",
  "transportation_arrival_time": "16:00",
  "transportation_arrival_terminal": "2",
  "transportation_arrival_number": "IB8867",
  "special_requests": "One of the passengers is a RMP.",
  "arrival_date": "2021-12-29",
  "arrival_time": "10:00",
  "departure_date": "2021-12-30",
  "departure_time": "10:00"
}

Booking [/bookings/{id}]

Modify a Booking [PUT]

Works the same way as the POST, please don't include the fields: id, parking_id, created_at, canceled_at.

Cancel a Booking [DELETE]

Possible HTTP status codes:

Code Description
204 No contents (OK!)
400 Bad request, f.i. wrong phone number, missing field, etc
401 Unauthorized, f.i. No channel token was provided
403 Forbidden, f.i. This channel has no permission for the booking
404 Not found, f.i. Booking not found
409 Conflict, f.i. Booking already canceled or time restricted

No parameters are needed, just DELETE /bookings/{id} and if the time constraint check (some parkings won't allow cancelling when the booking arrival is past), the API will return an empty body with a 204 No content HTTP status code (meaning everyghing went all right).

If a 409 Conflict status code is returned it means that the booking is not in a correct status (it might have been already canceled or it cannot be canceled) or the time limits are not being respected and that booking is not allowed to be canceled. Check the message for details.

If the status is 403 Not allowed means that the client is not correctly authenticated or is trying to cancel a booking that does not belong to him.

The api can return other errors (50x when is a problem in the server). But, as always when the API returns an error it also returns a message field with a message that specifies the details of the problem.