Partner API
Sep 21, 2026 10:12 AM

Authentication

OAuth2 (Resource Owner Password Credentials): obtaining and refreshing an access token, its lifetime, and the authorization header for Hostme API requests.

The Hostme API uses OAuth2 with the Resource Owner Password Credentials scheme (password flow). You obtain a token with the login/password of a service account and attach it to every request in the Authorization: Bearer <token> header.

Step 1. Obtaining a token

The token is issued by POST /Token in application/x-www-form-urlencoded format:

Terminal window
curl -X POST https://api.hostmeapp.com/Token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=password" \
-d "username=YOUR_USERNAME" \
-d "password=YOUR_PASSWORD"

Partners do not need to pass client_id or scope — grant_type, username and password are enough. (Hostme’s internal Admin Panel additionally sends client_id=panel, but partner integrations don’t need it.)

Response:

{
"access_token": "eyJhbGciOiJ...",
"token_type": "bearer",
"expires_in": 86399
}
FieldDescription
access_tokenAccess token. Attached to every API request.
token_typeToken type — bearer.
expires_inToken lifetime in seconds.

refresh_token is not returned in the POST /Token response — once expires_in elapses, obtain a new token by repeating the request with the login/password.

Endpoint and environments

EnvironmentToken endpoint
Productionhttps://api.hostmeapp.com/Token
QA / Testhttps://api-qa.hostmeapp.com/Token

About swagger. The spec declares OAuth2 with tokenUrl: https://service.hostmeapp.com/token and scope All — that is the official authorization server. In practice the token is also accepted on the base API domain ({API_BASE}/Token) — this is how the production panel signs in, and this path is recommended for partner integrations. Sending scope is optional.

If your integration is published as an app in the “Integrations” section, the password grant above is neither needed nor suitable: the partner does not store the restaurant’s account login and password. Instead, the restaurant connects your app and Hostme issues it a Client ID / Client Secret pair — it is shown in the app settings, and the restaurant copies it into your dashboard.

The pair is issued per connection, that is per restaurant, not one per partner. However many restaurants have connected the app — that’s how many pairs you have, and a token obtained with a pair works only with that restaurant: its identifier is baked into the token itself, so there is no need to pass restaurantId separately when requesting a token.

Terminal window
curl -X POST https://api.hostmeapp.com/api/pos/apps/{appId}/security/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET"

{appId} is your app’s identifier in the Hostme catalog (for example airsales).

The response is the same as for the password grant:

{
"access_token": "eyJhbGciOiJ...",
"token_type": "Bearer",
"expires_in": 43199
}
EnvironmentToken endpoint
Productionhttps://api.hostmeapp.com/api/pos/apps/{appId}/security/oauth/token
QA / Testhttps://api-qa.hostmeapp.com/api/pos/apps/{appId}/security/oauth/token

What to keep in mind

  • Do not pass scope. Permissions come from your app’s manifest, not from the request. A scope sent along is ignored — including scope=All, which used to cause invalid_scope.
  • The lifetime is shorter than for the password grant and may differ between apps: for example, for apps with real-time reservation access it is 12 hours (expires_in: 43199). Read expires_in from the response, don’t hardcode a constant.
  • No refresh_token is issued — come back for a new token with the same pair.
  • Wrong pair → 401. The secret is compared in constant time, and the response does not distinguish “no such client_id” from “wrong secret”.
  • When a restaurant disconnects the app, access is revoked instantly: the pair resolver only looks at active connections, so you won’t get a new token, and the one already issued stops working.
  • The token comes encrypted (JWE, five parts): you cannot parse it on your side to read the claims — treat it as an opaque string.

How such a token behaves differently

Reservations created with this token are automatically tagged with your app (vendorKey / vendorName in the reservation contract) and show up in the restaurant’s analytics as your channel — nothing needs to be set manually. Their source field is web.

Permissions are limited by the manifest: endpoints not covered by the requested permissions respond with 403, even if the token is valid. For instance, an app with access to reservations and availability cannot see reservation requests (GET /api/rsv/admin/restaurants/{id}/requests).

Step 2. Using the token

Attach access_token to every request:

Terminal window
curl https://api.hostmeapp.com/api/core/admin/account/me \
-H "Authorization: Bearer eyJhbGciOiJ..."

Without a valid token the API returns 401 Unauthorized.

Step 3. Which restaurant is available

GET /api/core/admin/account/me

After obtaining a token, find out which restaurants you have access to, and their restaurantId:

Terminal window
curl https://api.hostmeapp.com/api/core/admin/account/me \
-H "Authorization: Bearer <token>"

The response is a UserInfoContract. Key fields:

FieldTypeDescription
idstringUser/account identifier
emailstringEmail
fullNamestringName
partnerIdstringPartner identifier (if the account is a partner account)
roles[]arrayRoles by restaurant: restaurantId, restaurantName, name, type
restaurants[]arrayAvailable restaurants (see below)

A restaurants[] element (RestaurantSummaryContract):

FieldTypeDescription
idintegerrestaurantId — use it in /restaurants/{restaurantId}/... paths
namestringName
address, city, country, countryShortstringAddress
timeZonestringRestaurant time zone
isVerifiedbooleanVerified
isSuspendedbooleanSuspended
isOnlinebooleanOnline reservations are enabled
rolestringYour role in the restaurant

Token types and API behavior

The behavior of some endpoints depends on the token type the request is made with:

Token typeWho it isHow records are created
HostmeA host/manager in the Admin PanelOn behalf of the current user
PartnerA partner accountOn behalf of the current user (host/manager)
VendorAn external app (POS, CRM)On behalf of the external app; VendorAppId is set automatically

Example: when creating a reservation (POST .../reservations) with a Vendor token, the reservation is created on behalf of the external app, and when listing with scope App, VendorAppId is substituted automatically and a date range is required (no more than 60 days). See Reservations and Partner reservations for details.

Partner token

POST /api/core/admin/account/partners/token

For partner scenarios the platform supports issuing a partner token via POST /api/core/admin/account/partners/token (body — PartnerTokenRequest). The exact request schema is agreed individually when the partner is onboarded.

The exact format of the PartnerTokenRequest body and the conditions for issuing a partner token are provided by the Hostme team during partner onboarding — see App registration.

Handling authentication errors

CodeCauseWhat to do
401Token is missing, expired or invalidObtain a new token; check the Authorization header
403No permission for the restaurant/actionCheck the account’s access to restaurantId

More about errors — in Errors and response codes.