Skip to content

Commit

Permalink
Adjust texts
Browse files Browse the repository at this point in the history
  • Loading branch information
smily-ivan committed Aug 4, 2023
1 parent c5e3637 commit b53a503
Show file tree
Hide file tree
Showing 11 changed files with 434 additions and 162 deletions.
151 changes: 144 additions & 7 deletions content/guides/accounts-synchronization.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,39 @@

## Preface

With this endpoint you can import all accounts who wants to publish their listings on your website. As a next step you can sign a contracts with these accounts if needed, create accounts on your side, etc.
The Accounts endpoint enables partners to retrieve a list of accounts interested in publishing their listings on the partner's website. Partners can use this endpoint to identify potential accounts for onboarding, which may involve signing contracts and other necessary steps.

## Get all accounts
## Get All Accounts

You can find detailed specification in [Swagger documentation](https://demo.platforms.bookingsync.com/api-docs/index.html)
Retrieve a list of accounts that wish to publish their listings on a partner's website. Refer to the [Swagger documentation](https://demo.platforms.bookingsync.com/api-docs/index.html) for detailed specifications.

> This endpoint does not support pagination.
> Note: Pagination is not supported for this endpoint.
> Don't forget to disable accounts and their rentals if you don't see them anymore in current list
> Important: If an account is no longer visible in the list, ensure to disable the corresponding account and rentals.
> We suggest to do synchronization of accounts every 12-24 hours.
> Recommendation: We suggest to do synchronization of accounts every 12-24 hours.

## Code example in cURL

~~~bash
TOKEN="<YOUR_TOKEN>"
API_URL="<API_URL>"

curl -X GET \
"$API_URL/api/ota/v1/accounts" \
-H "User-Agent: API Client" \
-H "Accept: application/vnd.api+json" \
-H "Content-Type: application/vnd.api+json" \
-H "Authorization: Bearer $TOKEN"
~~~

## Code example in Ruby

~~~ruby
require 'excon'
require 'json'

token = "<YOUR_TOKEN>"
api_url = "<API_URL>"
media_type = "application/vnd.api+json"
Expand All @@ -30,7 +50,7 @@ options = {
}
}
request = Excon.new(URI.join(api_url, "/api/ota/v1/accounts").to_s, options)
response = request.request({ method: :get })
response = request.request(method: :get)

response.status

Expand All @@ -45,3 +65,120 @@ end
accounts_for_disabling = already_import_accounts_ids - json["data"].pluck("id")
disable_accounts_and_rentals(accounts_for_disabling) # Disable accounts
~~~

Replace `<YOUR_TOKEN>` and `<API_URL>` with your specific authentication token and API URL in the provided example.

## Code example in Python

~~~python
import requests

token = "<YOUR_TOKEN>"
api_url = "<API_URL>"
media_type = "application/vnd.api+json"
headers = {
"User-Agent": "API Client",
"Accept": media_type,
"Content-Type": media_type,
"Authorization": f"Bearer {token}"
}
response = requests.get(f"{api_url}/api/ota/v1/accounts", headers=headers)

response_status = response.status_code

# Assuming you have a function to retrieve already imported account IDs: get_imported_accounts_ids
already_import_accounts_ids = get_imported_accounts_ids()

json_data = response.json()
for account in json_data["data"]:
# Import accounts
import_account(account["id"], account["attributes"]["name"])

accounts_for_disabling = [account_id for account_id in already_import_accounts_ids if account_id not in [a["id"] for a in json_data["data"]]]
disable_accounts_and_rentals(accounts_for_disabling) # Disable accounts
~~~

Please replace `<YOUR_TOKEN>` and `<API_URL>` with your actual authentication token and API URL in the Python code. Additionally, make sure you have the necessary functions **get_imported_accounts_ids**, **import_account**, and **disable_accounts_and_rentals** defined and implemented in your Python script.

## Code example in Java

~~~java
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.json.JSONArray;
import org.json.JSONObject;

public class AccountSynchronization {

public static void main(String[] args) {
String token = "<YOUR_TOKEN>";
String api_url = "<API_URL>";
MediaType mediaType = MediaType.parse("application/vnd.api+json");

OkHttpClient client = new OkHttpClient();

Request request = new Request.Builder()
.url(api_url + "/api/ota/v1/accounts")
.addHeader("User-Agent", "API Client")
.addHeader("Accept", mediaType.toString())
.addHeader("Content-Type", mediaType.toString())
.addHeader("Authorization", "Bearer " + token)
.build();

try {
Response response = client.newCall(request).execute();
int responseStatus = response.code();

// Assuming you have a function to retrieve already imported account IDs: getImportedAccountIds()
JSONArray alreadyImportAccountIds = getImportedAccountIds();

JSONObject responseBody = new JSONObject(response.body().string());
JSONArray accounts = responseBody.getJSONArray("data");

for (int i = 0; i < accounts.length(); i++) {
JSONObject account = accounts.getJSONObject(i);
// Import accounts
importAccount(account.getInt("id"), account.getJSONObject("attributes").getString("name"));
}

JSONArray accountsForDisabling = new JSONArray();
for (int i = 0; i < alreadyImportAccountIds.length(); i++) {
int accountId = alreadyImportAccountIds.getInt(i);
boolean found = false;
for (int j = 0; j < accounts.length(); j++) {
if (accounts.getJSONObject(j).getInt("id") == accountId) {
found = true;
break;
}
}
if (!found) {
accountsForDisabling.put(accountId);
}
}
// Disable accounts
disableAccountsAndRentals(accountsForDisabling);

} catch (Exception e) {
e.printStackTrace();
}
}

// Define your functions here:
private static JSONArray getImportedAccountIds() {
// Implement your logic to get imported account IDs
return new JSONArray();
}

private static void importAccount(int accountId, String accountName) {
// Implement your logic to import accounts
}

private static void disableAccountsAndRentals(JSONArray accountIds) {
// Implement your logic to disable accounts and rentals
}
}
~~~

Please replace `<YOUR_TOKEN>` and `<API_URL>` with your actual authentication token and API URL in the Java code. Additionally, implement the necessary functions **getImportedAccountIds**, **importAccount**, and **disableAccountsAndRentals** according to your requirements.
75 changes: 55 additions & 20 deletions content/guides/api-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,71 @@

## What is Smily Channel API?

Channel API allows you to sync Smily properties to your own website (aka Channel). You can choose which properties or accounts to display or not, get rentals availabilities, book rentals and collect payments.
The channel API helps channel partners to integrate with our API by providing “shortcuts” so that partners can pull off the required data they need without having to combine too many requests from our API.

## Who is Smily Channel API for?

TODO
The Smily Channel API is designed to be useful for a variety of platforms. It's particularly valuable for:

- **Online Travel Agencies (OTAs)**
- **Marketplaces**
- **Tour Operators**
- **Niche Channels**

**Create Your Own Portal:** Additionally, the Smily offers the flexibility to build entire Marketplaces or Niche Channels according to your vision. Explore this capability further on our [Your Own Portal](https://www.smily.com/en/your-own-portal) page.

## Why would I use Smily Channel API?

This API was developed to make integration with our partners easier. If you want to look at all features of our system, please refer to [BookingSync Universe API ](https://developers.bookingsync.com/).
The Smily Channel API presents an optimal way to easily onboard new properties onto your system. Designed with our partners in mind, this API simplifies the integration journey.

It's important to highlight that our more extensive feature set is available through the [BookingSync Universe API ](https://developers.bookingsync.com/). While the Smily Channel API offers speedy integration, unlocking the full range of features in the BookingSync Universe API might take more time and expertise from skilled engineers.

In essence, the Smily Channel API provides a straightforward and speedy integration, while the BookingSync Universe API offers a wider range of features that require more time and technical know-how.

## How the Smily Channel API works?

In general, there are 3 steps you have to do:
The Smily Channel API is designed to synchronize account data, rentals, and facilitate bookings between Smily Channel and our partners’ platforms. Below is a detailed step-by-step guide on how to utilize our API for a seamless synchronization process.

### 1. Fetching Accounts

The first step to integration is to fetch the list of accounts interested in publishing their listings on your platform. You can do this by making a GET request to the `/accounts` endpoint. It’s recommended to perform this operation regularly to keep the accounts data up-to-date.

### 2. Accounts Onboarding

After fetching the accounts, the next step is to onboard them. This process involves signing contracts, registering them in your system, and performing any other necessary setup operations.

### 3. Fetching Rental Information

Once the accounts are onboarded, it’s time to fetch their associated rentals. This process happens in several stages:

**3.1 Fetching Base Rental Information**

First, fetch the base information of the rentals by making a GET request to the `/rentals` endpoint. This includes details like descriptions, tags, amenities, etc. It is advised to refresh this information once a day to keep it up-to-date.

**3.2 Fetching Rental Availabilities**

The next step is to fetch the availability status of these rentals. You can do this by making an GET request to the `/rentals` endpoint. It's recommended to refresh availability data every hour.

**3.3 Fetching Rental Prices**

Fetch the prices of the rentals by making a GET request to the `/api/ota/v1/los-record-export-urls` endpoint. We update prices every 12 hours, no sense to update it more often.

**3.4 Unpublished Rentals**

Lastly, it’s crucial to remove any rentals that are no longer available. If a rental is unpublished from the Smily Channel, be sure to reflect this change in your system to avoid booking unavailable rentals.

### 4. Booking Creation

When a customer makes a booking request on your platform, the following steps need to be followed:

**4.1 Create a Quote**

First, confirm the price and availability of the chosen rental by creating a quote. You can do this by making a POST request to the `/quotes` endpoint. The response will provide you with the confirmed price and availability status.

1. Manage accounts that are ready to publish their listings on your website - regularly refresh the list and onboard them.
2. Manage rentals of onboarded accounts - regularly refresh descriptions, prices and availabilities.
3. Manage bookings. This step depends on how you want to process the payments - on your side, or on our side.
**4.2 Create a Booking**

If the rental is available, proceed to create a booking. Make a POST request to the `/bookings` endpoint with a price not less than the one provided in the quote response.

The API is fully [JSONAPI 1.0 compliant](http://jsonapi.org).
**4.3 Confirm Booking with Payment**

1. Get accounts
2. approve/reject them
3. sign contracts/register/oboarding/etc
4. get rentals of approved accounts
4.1 Get rentals info (refresh once a day)
4.2 Get rentals availabilities (refresh every hour)
4.3 Get rentals prices (every 12 hours)
4.4 Remove unpublished rentals
5. Booking creation:
5.1 Create quote to confirm price and availability.
5.2 Create booking with price not less than in quote response
5.4 Create payment to confirm booking
Lastly, confirm the booking by making a payment. You can do this by sending a POST request to the `/payments` endpoint. This final step ensures the booking is confirmed and the rental is successfully reserved for the customer.
68 changes: 43 additions & 25 deletions content/guides/booking-cancelation.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# Booking cancelation
# Booking Cancelation

1. TOC
{:toc}

## Preface

Bookings could be canceled according to the rental's cancelation policy. You can get cancelation policy from rental's enpoint, usually it looks like:
The Booking Cancellation API allows you to cancel bookings according to the rental's cancellation policy. The cancellation policy can be retrieved from the rental's endpoint and includes details such as eligible cancellation days and penalty percentages.

~~~js
"cancelation-policy-items": [
Expand All @@ -21,53 +21,71 @@ Bookings could be canceled according to the rental's cancelation policy. You can
]
~~~

In this case you can cancel the booking not later than 2 days before check-in. And penalty will be 10% from the booking final price.
In this example, a booking can be canceled up to 2 days before check-in with a penalty of 10% from the booking's final price.

## Booking cancelation
## Booking Cancellation Process

You can find detailed specification in [Swagger documentation](https://demo.platforms.bookingsync.com/api-docs/index.html)
To cancel a booking, follow these steps:

1. Retrieve the cancellation policy from the rental's endpoint. Refer to the [Swagger documentation](https://demo.platforms.bookingsync.com/api-docs/index.html) for detailed specifications.
2. Use the provided cancellation policy to determine the eligible cancellation days and penalty percentage.
3. Make a PATCH request to the booking cancellation endpoint:

~~~ruby
token = "<YOUR_TOKEN>"
api_url = "<API_URL>"
media_type = "application/vnd.api+json"

# Set headers and options for the request
headers = {
"User-Agent": "Api client",
"Accept": media_type,
"Content-Type": media_type,
"Authorization": "Bearer #{token}"
}

options = {
headers: {
"User-Agent" => "Api client",
"Accept" => media_type,
"Content-Type" => media_type,
"Authorization" => "Bearer #{token}"
}
headers: headers
}

request = Excon.new(URI.join(api_url, "/bookings/#{booking_id}/cancel").to_s, options)
# Construct the request
booking_id = "<BOOKING_ID>"
cancelation_reason = "canceled_by_traveller_other"
cancelation_description = "health concern"
channel_cancelation_cost = "80.0"
currency = "USD"

payload = {
data: {
attributes: {
"cancelation-reason": "canceled_by_traveller_other",
"cancelation-description": "health concern",
"channel-cancelation-cost": "80.0",
"currency": "USD"
},
type: "bookings",
id: booking_id
id: booking_id,
attributes: {
"cancelation-reason": cancelation_reason,
"cancelation-description": cancelation_description,
"channel-cancelation-cost": channel_cancelation_cost,
"currency": currency
}
}
}
response = request.request({
method: :patch,
body: payload.to_json
})

request_url = URI.join(api_url, "/bookings/#{booking_id}/cancel").to_s
request = Excon.new(request_url, options)

# Send the request and handle the response
response = request.request(method: :patch, body: payload.to_json)
json = JSON.parse(response.body)

if response.status == 200
booking_canceled_at = json["data"]["attributes"]["canceled-at"]
# update new booking information
# Update new booking information
else
handle_errors(json)
end
~~~

In some cases you can get a 422 error. Response will look like this:
## Possible Validation Error

In case of a validation error, the response will resemble the following:

~~~js
{
Expand Down
Loading

0 comments on commit b53a503

Please sign in to comment.