Introduction

Liigu API is designed for third parties who want to integrate Liigu's features with their system. Liigu API uses GraphQL.
If you are new to GraphQL, take some time to learn about it from here.

The API supports the following flows:

  • Partial booking process where rates are shown on a third party website and the customer is redirected to Liigu's website
  • Full booking process where rates are shown on a third party website and the booking is also created on the third party website

API Explorer

You can try out queries and mutation with our API Explorer.

Making requests

Liigu API can be accessed over HTTPS. You can use any HTTP library or any GraphQL client to make a request.

Endpoints

All requests go to a single endpoint:

https://api.liigu.me/graphql

Production and Sandbox use the same endpoint with different credentials.

Authentication

Authentication is performed via HTTP basic authentication:

curl -u "username:password" https://api.liigu.me/graphql

Content-type header

Content type of the query must be application/json.

Message body

Message body must be a JSON object with query and variables if applicable.

The value for the query must be a single string containing a well-formatted GraphQL document. You can also reference variables.

{
	"query": "query { ping(ping: $message) }",
	"variables": {
		"message": "this is text variable"
	}
}

Example request

Here is an example query:

GraphQL query

query {
	ping(ping: "echo") {
		pong
	}
}

JSON Object

{
	"query": "query { ping(ping:\"echo\") { pong }}"
}

CURL

curl -u "username:password" -H "Content-Type: application/json" -X POST https://api.liigu.me/graphql -d '{"query": "query { ping(ping:\"echo\") { pong }}"}'

Response

{
	"data": {
		"ping": {
			"pong": "echo"
		}
	}
}

Error handling

Unlike REST API, GraphQL does not rely on HTTP status codes. Liigu API always returns a JSON body and the status code is always 200.

If an error occurs, the response body will include a top level errors array that describes the error.

For example, if there is a problem with your credentials, the following is returned:

Response

{
	"errors": [
		{
			"message": "Context creation failed: Failed to authenticate, please try again later!",
			"extensions": {
				"code": "UNAUTHENTICATED"
			}
		}
	]
}

Pagination

If pagination is supported in the response, the response objects are wrapped in the following object:

{
	"branches": {
		"edges": [],
		"pageInfo": {
			"hasNextPage": true,
			"endCursor": "AYEBCg"
		}
	}
}

To retrieve the next set of items, you can add the argument after and set its value to endCursor.

query {
   branches(after: "AYEBCg") {
      ...
   }
}

Branches

To retrieve available rates by using Availability, you need to know which branches (locations) are available.
It is good practice to synchronise the branches database at least once a week.

Every branch has a unique id that can be used to retrieve the list of available rates in that branch.

GraphQL query

query {
	branches {
		edges {
			node {
				id
				location {
					name
				}
			}
		}
		pageInfo {
			hasNextPage
			endCursor
		}
	}
}

Response

{
	"data": {
		"branches": {
			"edges": [
				{
					"node": {
						"id": "NCE",
						"location": {
							"name": "Nice Airport"
						}
					}
				},
				{
					"node": {
						"id": "OPO",
						"location": {
							"name": "Porto Airport"
						}
					}
				}
			],
			"pageInfo": {
				"hasNextPage": true,
				"endCursor": "AYEBCg"
			}
		}
	}
}

Check our API Explorer for full specifications.

Retrieving available rates and redirecting customers to Liigu's website

To redirect a customer to Liigu's website, Liigu API returns a deep link to the offer the customer selected.

GraphQL query

query {
	availability(
		input: {
			pickUpBranchId: "NCE"
			pickUpBranchDateTime: "2026-01-05T12:00:00"
			dropOffBranchId: "NCE"
			dropOffBranchDateTime: "2026-01-11T16:45:00"
			residenceCountryCode: "US"
			driverAge: 30
		}
	) {
		rates {
			vehicle {
				code
				model
			}
			packages {
				deepLink
				payments {
					total {
						amount
						currency
					}
				}
			}
		}
	}
}

Response

{
	"data": {
		"availability": {
			"rates": [
				{
					"vehicle": {
						"code": "CWAR",
						"model": "Opel/Vauxhall Astra Sports Tourer"
					},
					"packages": [
						{
							"deepLink": "https://liigu.me/en-us/results?offer=1",
							"payments": {
								"total": {
									"amount": "449.78",
									"currency": "EUR"
								}
							}
						}
					]
				},
				{
					"vehicle": {
						"code": "IDAR",
						"model": "Renault Megane"
					},
					"packages": [
						{
							"deepLink": "https://liigu.me/en-us/results?offer=2",
							"payments": {
								"total": {
									"amount": "491.04",
									"currency": "EUR"
								}
							}
						}
					]
				}
			]
		}
	}
}

Retrieving available rates and making a booking

Every package in an availability response has a rate reference. Rate reference can be used to make a booking.

Availability

GraphQL query

query {
	availability(
		input: {
			pickUpBranchId: "NCE"
			pickUpBranchDateTime: "2026-01-05T12:00:00"
			dropOffBranchId: "NCE"
			dropOffBranchDateTime: "2026-01-11T16:45:00"
			residenceCountryCode: "US"
			driverAge: 30
		}
	) {
		rates {
			vehicle {
				code
				model
			}
			packages {
				rateReference
				payments {
					total {
						amount
						currency
					}
				}
			}
		}
	}
}

Response

{
	"data": {
		"availability": {
			"rates": [
				{
					"vehicle": {
						"code": "CWAR",
						"model": "Opel/Vauxhall Astra Sports Tourer"
					},
					"packages": [
						{
							"rateReference": "7_O_Jwn0-WTOBU8zQ9rsaqmJYZ1y7feH5ebv6x",
							"payments": {
								"total": {
									"amount": "449.78",
									"currency": "EUR"
								}
							}
						}
					]
				},
				{
					"vehicle": {
						"code": "IDAR",
						"model": "Renault Megane"
					},
					"packages": [
						{
							"rateReference": "7_O6T-baV7fKk0s9TX3PrOjae9j9xPnbWqa8",
							"payments": {
								"total": {
									"amount": "491.04",
									"currency": "EUR"
								}
							}
						}
					]
				}
			]
		}
	}
}

Booking

To make a booking, you need to pass the rate reference from the availability response. It is also good practice to send your own unique reference which can be used to link Liigu's booking to your booking.

GraphQL query

mutation {
	createBooking(
		input: {
			rateReference: "7_O_Jwn0-WTOBU8zQ9rsaqmJYZ1y7feH5ebv6x"
			externalReference: "your-unique-reference-for-this-booking"
			customer: {
				firstName: "John"
				lastName: "Smith"
				email: "support@liigu.me"
				birthDate: "1998-05-21"
				phone: "+447818005232"
				countryCode: "GB"
				city: "London"
				address: "51 Liigu Road"
				postalCode: "W54 0XP"
				languageCode: "en-gb"
			}
			flightNumber: "BA1476"
			extras: [{ code: "7", quantity: 2 }]
		}
	) {
		booking {
			id
		}
	}
}

Response

{
	"data": {
		"booking": {
			"id": 57483948
		}
	}
}

Terms of Service

GraphQL query

query {
	termsOfService(languageCode: "fr-fr", contentType: HTML) {
		sections {
			label
			title
			content
		}
	}
}

Response

{
	"data": {
		"termsOfService": {
			"sections": [
				{
					"label": "terms-of-service-summary",
					"title": "Conditions générales d'utilisation",
					"content": "<p>Les présentes conditions générales..."
				},
				{
					"label": "general-information",
					"title": "Informations à caractère général",
					"content": "<p>Nous sommes Liigu OÜ..."
				}
			]
		}
	}
}

Webhooks Overview

Webhooks are HTTP callbacks triggered by specific events within the system. These callbacks are configured by users to notify external systems or services about events such as booking creation, modification, or cancellation. Each webhook configuration consists of a URL to which the payload will be sent, along with optional headers for authentication and authorization.

Webhook Rules

  • Webhook payloads are sent via HTTP POST requests.

  • We also add X-Hmac signature to the headers for additional authentication

  • We wait for the response for 5 seconds after which we mark it as failed and will retry based on our Retry Policy

  • The expected response from the receiver is HTTP 200 response. Any other response will be marked as failed and we will retry to send it again.

  • Retry Policy:

    • Attempts are made at least once but a maximum of 5 times.
    • Retry intervals: 1m, 5m, 10m, 30m.

HMAC Authentication for Webhooks

HMAC (Hash-based Message Authentication Code) signature is used to ensure the integrity and authenticity of webhook requests sent by our service. The signature is generated using a secret key shared between our service and the receiver. Upon receiving a webhook request, the receiver can verify the request's authenticity by computing the HMAC signature and comparing it with the signature provided in the request header.

Secret Key

The secret key is used to generate the HMAC signature and must be securely shared between our service and the receiver. Please keep the secret key confidential to maintain the security of the webhook communication.

Request the secret key from Liigu support.

Verifying HMAC Signature

Upon receiving a webhook request, the receiver should verify the HMAC signature to ensure the request's authenticity. Follow these steps to verify the HMAC signature:

  1. Extract the HMAC signature from the request header X-Hmac.
  2. Calculate the HMAC signature using the received request body and the shared secret key.
  3. Compare the calculated HMAC signature with the received HMAC signature.

Below is an example code snippet in TypeScript to verify the HMAC signature:

import crypto from 'crypto';
import express from 'express';

// This key has to be requested from Liigu support
const secretKey = 'YOUR_SECRET_KEY';

const app = express();

app.use(express.json());

app.post('/webhook-receiver', (req, res) => {
    const receivedHmac = req.headers['x-hmac'] as string;
    const requestBody = JSON.stringify(req.body);

    const calculatedHmac = generateHMACSignature(secretKey, requestBody);

    if (receivedHmac === calculatedHmac) {
        // HMAC verification successful
        res.status(200).send('Webhook request verified.');
    } else {
        // HMAC verification failed
        res.status(403).send('Forbidden: HMAC verification failed.');
    }
});

function generateHMACSignature(secretKey: string, requestBody: string): string {
    const hmac = crypto.createHmac('sha256', secretKey);
    hmac.update(requestBody);
    return hmac.digest('hex');
}

Webhook Payload

  • The webhook payload contains information about the event triggered.

Webhook Payload example

{ 
    "id": "94ff51bf-768d-4a13-86d6-6a8c9d36bff9",
    "name": "booking.cancelled",
    "createdAt": "2006-01-02T15:04:05Z07:00",
    "data": { 
        "reservNum": 12345678,
        "version": "1",
        "brokerReference": "87654321",
        "supplierReference": "KHui8)UI90IOJ98u",
    },
}

Common Parameters

Parameter Required Type Description Example
id Yes string A unique id for the unique event.
  • If the booking is cancelled and we make more than one booking.cancelled webhook request then each request has the same id. If another booking is canceled a new unique id will be generated
"94ff51bf-768d-4a13-86d6-6a8c9d36bff9"
name Yes string

Enum:
  • booking.cancelled
The hook name:
  • booking.cancelled - The booking has been cancelled
"booking.cancelled"
createdAt Yes string <date-time> When the action happened "2006-01-02T15:04:05Z07:00"
data Yes object Event type specific data object
        
{ 
    "reservNum": 12345678,
    "version": "1",
    "brokerReference": "87654321",
    "supplierReference": "KHui8)UI90IOJ98u",
}
        
       

Event booking.cancelled

This event is triggered when the booking has been cancelled. For each booking, this can happen only once.

The webhook payload data will contain:

Parameter Required Type Description Example
reservNum Yes integer Reservation number 12345678
version Yes string Version of the booking "0"
brokerReference No string Broker provided reference value "87654321"
supplierReference No string Supplier provided reference value "KHui8)UI90IOJ98u"