Loading...
Cở chữ Aa- Aa+

Sophia PMS – Partner API (v1)

Overview

The Sophia PMS Partner API (v1) is a read-only API that enables authorized partners to retrieve data from hotels using Sophia PMS.

The API provides access to hotel properties, reservations, revenue reports, occupancy metrics, channel mix, and room availability. It allows partners to integrate hotel operational data into their own applications, reporting platforms, and business intelligence solutions.

Key Features

  • Hotel Properties: Retrieve the list of hotels accessible to the API key.
  • Reservations (Bookings): Retrieve booking lists and details, including guest information, room types, reservation status, rates, and stay dates.
  • Revenue and Performance Reports: Access revenue, Occupancy, Average Daily Rate (ADR), and Revenue per Available Room (RevPAR).
  • Channel Mix: Analyze revenue and room-night distribution by market segment or booking source.
  • Room Availability: Retrieve available room inventory by room type and date, including future dates.

1. Connection Information

Property Value
API Version v1
Base URL https://app.sophiapms.com/api/partner/v1
Data Format JSON (UTF-8)
HTTP Method GET only
Protocol HTTPS required
Maximum Date Range 30 days per request

The API is read-only and supports GET requests only. All requests must use HTTPS.

Endpoint Reference

Category Endpoint Description
Properties GET /properties Retrieve accessible hotel properties
Bookings GET /bookings Retrieve booking lists
Bookings GET /bookings/{booking_id} Retrieve booking details
Reports GET /reports/summary Revenue, Occupancy, ADR, and RevPAR
Reports GET /reports/channel-mix Revenue and distribution by booking channel
Inventory GET /inventory/vacant Available rooms by room type

2. API Authentication

Sophia issues each partner an API key in the format spk_.... The key must be included in the user-api-key HTTP header of every request.

GET /api/partner/v1/properties
Host: app.sophiapms.com
user-api-key: spk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Security Requirements

  • Never pass the API key through a query string.
  • Each API key can access only the hotel properties explicitly assigned to it.
  • API keys are stored as hashes and cannot be retrieved in their original form.
  • If a key is lost, contact Sophia to request a replacement. The previous key will be deactivated immediately.
  • When a key is revoked, requests using that key will be rejected within a maximum of one minute.

Partners must keep API keys confidential and must not expose them in public source code or share them with unauthorized systems.

3. Rate Limits

The API enforces rate limits per API key and hotel property.

Limit Default Value
Requests per minute per API key and property 20 requests
Concurrent booking-list requests for the same property 1 request

Limits may be adjusted for individual API keys.

Successful responses include the following headers:

  • X-RateLimit-Limit: Maximum number of requests allowed per minute.
  • X-RateLimit-Remaining: Number of requests remaining in the current minute.

When the limit is exceeded, the API returns HTTP 429 Too Many Requests with a Retry-After header indicating how many seconds to wait before retrying.

Recommended Practices

  • Synchronize data periodically, for example every 5–15 minutes, depending on business requirements.
  • Process requests sequentially for each hotel property.
  • Avoid concurrent requests for the same property.
  • Respect the Retry-After header when receiving a 429 response.
  • Use pagination to retrieve all available records.

4. Response Format and Error Codes

4.1. Successful Responses

List endpoints generally return the following structure:

{
  "data": [
    {
      "id": "...",
      "type": "...",
      "attributes": {}
    }
  ],
  "meta": {
    "page": 1,
    "limit": 50,
    "total": 120
  }
}

Depending on the endpoint, data may be an array or an object containing data fields and nested collections.

4.2. Error Responses

{
  "errors": {
    "code": "validation_error",
    "title": "property_id is required."
  }
}

4.3. HTTP Error Codes

HTTP Status Error Code Description
400 validation_error Missing or invalid parameters
401 unauthorized Missing, invalid, or revoked API key
403 forbidden The API key does not have access to the requested property
403 https_required The request uses HTTP instead of HTTPS
404 not_found Booking or property not found
429 too_many_requests Rate limit exceeded or another request is running for the same property
500 server_error Internal server error; retry later
503 report_unavailable The report is temporarily unavailable

4.4. Data Conventions

  • Dates use the yyyy-MM-dd format.
  • Datetimes use the yyyy-MM-ddTHH:mm:ss format and the hotel's local time zone (UTC+7).
  • Monetary values are numeric and use the hotel's currency, typically VND.
  • Fields without available data are returned as null.

5. Hotel Properties

Endpoint: GET /properties

This endpoint returns the list of hotel properties accessible to the API key. The id field is the property_id required by the other endpoints.

Example request:

curl -H "user-api-key: spk_xxx" \
  "https://app.sophiapms.com/api/partner/v1/properties"

Example response:

{
  "data": [
    {
      "id": 10,
      "type": "property",
      "attributes": {
        "id": 10,
        "title": "Demo Sophia Hotel",
        "code": "DEMO",
        "address": "123 Le Loi",
        "city": "Ho Chi Minh",
        "country": "VN"
      }
    }
  ],
  "meta": {
    "total": 1
  }
}

Partners should call this endpoint before requesting bookings, reports, or room inventory.

6. Booking List

Endpoint: GET /bookings

This endpoint retrieves bookings by hotel property, arrival date range or departure date range, room status, and pagination parameters.

6.1. Request Parameters

Parameter Required Description
property_id Yes Hotel property ID
arrival_from, arrival_to Conditional Arrival date range; inclusive, in yyyy-MM-dd format
departure_from, departure_to Conditional Departure date range; inclusive, in yyyy-MM-dd format
status No One or more room statuses, separated by commas
page No Page number, starting at 1; defaults to 1
limit No Number of bookings per page; defaults to 50, maximum 100

At least one date range—arrival or departure—must be provided. If both ranges are supplied, the results must satisfy both conditions.

  • The _from and _to parameters must be supplied together.
  • The end date cannot be earlier than the start date.
  • Each date range is limited to 30 calendar days, inclusive.
  • Each returned record represents a booking group with the same arrival and departure dates. Rooms in a group booking with different stay dates are returned as separate records sharing the same booking_id.
  • Cancelled rooms are excluded. A booking with all rooms cancelled is not returned.
  • When filtering by status, a booking group is returned if at least one room matches the requested status. Its rooms array contains all non-cancelled rooms in that group.
  • Pagination and meta.total are based on the number of booking records, not the number of rooms.
  • Results are sorted by arrival date in ascending order.

Example request:

curl -H "user-api-key: spk_xxx" \
  "https://app.sophiapms.com/api/partner/v1/bookings?property_id=10&arrival_from=2026-10-01&arrival_to=2026-10-30&status=pending,checked_in&page=1&limit=50"

To retrieve all records, increment page until page * limit >= meta.total.

6.2. Group Booking Example

Suppose booking BK000123 contains four rooms:

Room Arrival Departure Status
101 2026-10-05 2026-10-07 pending
102 2026-10-05 2026-10-07 pending
103 2026-10-06 2026-10-08 pending
104 2026-10-05 2026-10-07 cancelled

The API returns two records because room 103 has different stay dates and room 104 has been cancelled.

Record ID Arrival Departure Rooms
{booking_id}_20261005_20261007 2026-10-05 2026-10-07 101, 102
{booking_id}_20261006_20261008 2026-10-06 2026-10-08 103

7. Booking Details

Endpoint: GET /bookings/{booking_id}?property_id={property_id}

Parameter Required Description
booking_id Yes Booking GUID obtained from the booking list
property_id Yes Hotel property ID

The response follows the same structure as the booking list, with data returned as an array. A group booking may contain multiple groups with different arrival and departure dates.

The API returns 404 not_found if the booking cannot be found or all its rooms have been cancelled.

7.1. Booking Fields

Field Description
id Booking-group ID in the format {booking_id}_{arrival yyyyMMdd}_{departure yyyyMMdd}. Use as the partner-side group key. If stay dates change, a room may move to a group with a new ID; use rooms[].id to track individual rooms.
booking_id Booking GUID in Sophia PMS, used by the details endpoint
property_id Hotel property ID
booking_code Booking reference in Sophia PMS
ota_reservation_code OTA or Channel Manager reservation code, if available
is_group Indicates whether the booking is a group booking
source Booking source object containing id and name
arrival_date, departure_date Arrival and departure dates for the group
nights Number of nights
rooms_count Number of rooms in the group
amount Total room amount for the group, equal to the sum of rooms[].amount
notes Booking notes
customer Booking contact; if unavailable, the primary guest of the first room may be used. May be null.
created_at, updated_at Creation and latest update timestamps for the booking or any room
rooms Array of rooms in the booking group

7.2. Room Fields

Field Description
id Room reservation GUID
reservation_number Room reservation number
ota_reservation_code OTA reservation code, if available
status, status_code Room status, as defined in Section 8
rent_type Rental type: day_night, monthly, or hourly
room_type Room type object containing id and name
room Assigned physical room; null if not yet assigned
occupancy Number of adults, children, and infants
rate Room rate; for monthly rentals, the rate for one month
discount_percent Discount percentage
breakfast Indicates whether breakfast is included
amount Room amount before discount: sum of days[].rate; if days is absent, rate multiplied by the number of nights. For monthly rentals, it equals rate.
days Daily rates (date, rate). For monthly rentals, each entry represents a monthly billing period starting on date.
guest Primary guest for the room; may be null
created_at, updated_at Room creation and update timestamps

8. Room Statuses

Room status is defined for each rooms[].status entry, not for the booking as a whole.

status status_code Description
pending 0 Reserved, not yet checked in
checked_in 1 Guest is currently staying
checked_out 2 Guest has checked out
cleaned 3 Guest has checked out and the room has been cleaned
no_show 4 Guest did not arrive

The status filter accepts only the values listed above. Passing cancelled or another unsupported value returns 400 validation_error.

Cancelled rooms are not returned. If a room disappears from a synchronization result for the same date range, it may have been cancelled or moved to a different date group. Call the booking details endpoint to verify its current state.

9. Revenue and Performance Reports

The reporting endpoints share the following parameters:

Parameter Required Description
property_id Yes Hotel property ID
from Yes Start date in yyyy-MM-dd format
to Yes End date in yyyy-MM-dd format

The date range is inclusive and limited to 30 days per request. These endpoints use the same API key and rate limits as booking endpoints.

9.1. Revenue Calculation Rules

Revenue includes amounts already posted to the folio, such as posted room charges and entered services. Therefore, to must not be later than the hotel's current business date, returned in meta.business_date.

  • revenue: Revenue including VAT and service charges.
  • revenue_ex_vat: Revenue excluding VAT but including service charges.
  • total: Total revenue.
  • room: Room revenue.
  • extra: Service revenue.

Room revenue is calculated by stay night, while service revenue is calculated by posting date.

room_nights_sold counts nights with posted room revenue greater than 10. Complimentary room nights with a rate of zero are excluded. room_nights_available is calculated from rooms in operation, excluding virtual and combined room types and subtracting OOO rooms for each date.

9.2. Revenue, Occupancy, ADR, and RevPAR

Endpoint: GET /reports/summary

Example request:

curl -H "user-api-key: spk_xxx" \
  "https://app.sophiapms.com/api/partner/v1/reports/summary?property_id=10&from=2026-10-01&to=2026-10-27&group_by=week"

The optional group_by parameter supports:

Value Description
day Daily grouping; default
week Weekly grouping, starting Monday
month Monthly grouping
year Yearly grouping

The response includes totals for the entire requested date range and periods[] for individual reporting periods. The first or last period may cover only part of a week or month.

Field Description
period Period key: date (yyyy-MM-dd), Monday of the week, month (yyyy-MM), or year (yyyy); null for totals
from, to Part of the period included in the requested date range
days Number of days in the included period
revenue Revenue including VAT and service charges: total, room, and extra
revenue_ex_vat Revenue excluding VAT but including service charges: total, room, and extra
room_nights_sold Sold room nights with room revenue greater than 10
room_nights_available Available room nights after subtracting OOO rooms for each date
out_of_order_room_nights Number of OOO room nights
occupancy_percent Occupancy percentage, or null if the denominator is zero
adr, adr_ex_vat Average room rate per sold night, including or excluding VAT
revpar, revpar_ex_vat Room revenue per available room night, including or excluding VAT

Calculation formulas:

  • Occupancy (%) = room_nights_sold / room_nights_available × 100.
  • ADR = Room revenue / room_nights_sold.
  • RevPAR = Room revenue / room_nights_available.

The corresponding excluding-VAT metrics use room revenue excluding VAT. The data object also includes property_id, from, to, group_by, currency, and sellable_rooms (rooms in operation before subtracting OOO rooms). The API returns null when a denominator is zero.

9.3. Channel Mix

Endpoint: GET /reports/channel-mix

This endpoint provides revenue and distribution by market segment or booking source.

Example request to retrieve data by booking source:

curl -H "user-api-key: spk_xxx" \
  "https://app.sophiapms.com/api/partner/v1/reports/channel-mix?property_id=10&from=2026-10-01&to=2026-10-27&level=source"

The level parameter supports:

  • segment (default): Groups data by market segment, such as OTA, Travel Agent, Direct, or Corporate.
  • source: Groups data by individual booking source, such as Booking.com, Agoda, or a corporate account, and includes the associated market segment.
Field Description
id, name Segment or source ID and name
segment Associated segment; available when level=source. It is null when level=segment.
revenue Revenue including VAT and service charges
revenue_ex_vat Revenue excluding VAT but including service charges
room_nights Sold room nights for the channel
adr, adr_ex_vat Average room rate for the channel
share_percent Percentage of total revenue, including VAT
room_nights_share_percent Percentage of total sold room nights

Sources without an assigned segment are grouped under Other, with id = 0. The items array is sorted by descending revenue. The totals object contains overall revenue, revenue_ex_vat, room_nights, adr, and adr_ex_vat.

10. Room Availability by Room Type

Endpoint: GET /inventory/vacant

This endpoint returns the number of rooms in operation, sold or reserved rooms, OOO rooms, and vacant rooms by date and room type.

Example request:

curl -H "user-api-key: spk_xxx" \
  "https://app.sophiapms.com/api/partner/v1/inventory/vacant?property_id=10&from=2026-10-28&to=2026-11-05"

Future dates are supported. Availability is calculated based on existing bookings at the time of the request.

Field Description
id, name Room type ID and name
total_rooms Number of rooms in operation for the room type
sold Rooms sold or reserved for the date, including reservations not yet checked in and current stays
out_of_order Number of OOO rooms for the date
vacant Number of vacant rooms

Formula:

vacant = max(0, total_rooms - sold - out_of_order)

Virtual and combined room types are excluded. The days[] array contains daily availability data. Each days[].room_types[] array contains room-type details, while days[].totals provides the total for the date.

Note: Room availability changes as bookings are created or updated. Partners should retrieve this endpoint when current availability is required rather than storing results for extended periods.

11. cURL Examples

Retrieve accessible properties:

curl -H "user-api-key: spk_xxx" \
  "https://app.sophiapms.com/api/partner/v1/properties"

Retrieve bookings:

curl -H "user-api-key: spk_xxx" \
  "https://app.sophiapms.com/api/partner/v1/bookings?property_id=10&arrival_from=2026-10-01&arrival_to=2026-10-30"

Retrieve booking details:

curl -H "user-api-key: spk_xxx" \
  "https://app.sophiapms.com/api/partner/v1/bookings/8b7d6e5f-0000-0000-0000-000000000000?property_id=10"

Retrieve weekly revenue, Occupancy, ADR, and RevPAR:

curl -H "user-api-key: spk_xxx" \
  "https://app.sophiapms.com/api/partner/v1/reports/summary?property_id=10&from=2026-10-01&to=2026-10-27&group_by=week"

Retrieve channel mix by source:

curl -H "user-api-key: spk_xxx" \
  "https://app.sophiapms.com/api/partner/v1/reports/channel-mix?property_id=10&from=2026-10-01&to=2026-10-27&level=source"

Retrieve room availability by room type, including future dates:

curl -H "user-api-key: spk_xxx" \
  "https://app.sophiapms.com/api/partner/v1/inventory/vacant?property_id=10&from=2026-10-28&to=2026-11-05"

C# Integration Example

The following example demonstrates how to send a request using HttpClient and wait when the rate limit is reached.

using System;
using System.Net.Http;
using System.Threading.Tasks;

public class SophiaPartnerApi
{
    public static async Task Main()
    {
        using (var http = new HttpClient
        {
            BaseAddress = new Uri(
                "https://app.sophiapms.com/api/partner/v1/")
        })
        {
            http.DefaultRequestHeaders.Add("user-api-key", "spk_xxx");

            var res = await http.GetAsync(
                "bookings?property_id=10&arrival_from=2026-10-01&arrival_to=2026-10-30");

            if ((int)res.StatusCode == 429)
            {
                var wait = res.Headers.RetryAfter?.Delta
                    ?? TimeSpan.FromSeconds(60);

                await Task.Delay(wait);

                res = await http.GetAsync(
                    "bookings?property_id=10&arrival_from=2026-10-01&arrival_to=2026-10-30");
            }

            var json = await res.Content.ReadAsStringAsync();
            Console.WriteLine(json);
        }
    }
}

This example demonstrates basic request handling and rate-limit recovery. Production integrations should also implement HTTP status validation, error handling, pagination, and appropriate retry policies.

12. Data Synchronization Guidelines

12.1. Booking Synchronization

  1. Call /properties to retrieve the list of accessible properties.
  2. For each property, retrieve upcoming bookings using an arrival date range from today through today + 29 days.
  3. Retrieve current stays using status=checked_in with an appropriate departure date range.
  4. Process every page until all records have been retrieved.
  5. Compare new records with stored data using booking id, rooms[].id, and updated_at to detect changes.

If a room no longer appears in the results for the same date range, call /bookings/{booking_id} to verify its current state. If the details endpoint returns 404, the entire booking has been cancelled or no longer exists under the API's rules.

12.2. Report Synchronization

  1. Revenue may change when hotel staff modify folio entries. Retrieve the previous day's data after the hotel completes its night audit, for example, every morning.
  2. For more accurate monthly figures, periodically refresh data for the current month.
  3. Split date ranges longer than 30 days into multiple requests, each covering no more than 30 days.
  4. When consolidating multiple periods, recalculate Occupancy, ADR, and RevPAR from the corresponding totals instead of averaging individual period percentages or rates.
  5. Do not set to later than meta.business_date; doing so returns 400 validation_error.

12.3. Rate-Limit Handling

When receiving 429 Too Many Requests, wait for the duration specified by Retry-After before retrying. Requests for the same hotel property should be processed sequentially.

13. Support

For API key replacement, additional property access, or rate-limit adjustments, please contact the Sophia PMS team.

Sophia PMS – Hotel Management System

Website: https://sophiasolution.com/

API Base URL: https://app.sophiapms.com/api/partner/v1

This documentation applies to Sophia PMS Partner API version v1.

Category
 29/10