Skip to content

Authentication

This API has two separate authentication mechanisms for two separate audiences. Don’t mix them up.

Audience Mechanism Used for
Organization owner (restaurant/hotel) JWT Bearer token (their own RestroLab login) /v1/third-party/credentials/* only
Your platform (the integrator) X-API-Key / X-API-Secret headers Every other endpoint; menu, orders, hotels, webhook

Owner authentication (credential management)

Section titled “Owner authentication (credential management)”

The /v1/third-party/credentials/ endpoints — list, create, revoke, rotate — are owner-only. They’re declared in openapi.json under the jwtAuth security scheme:

Field Value
Type http
Scheme bearer
Bearer format JWT
Authorization: Bearer <the owner's RestroLab JWT>

This is the tenant owner’s own RestroLab login, your platform never obtains or uses this token. It only exists so the owner can generate, rotate, or revoke the credential they then hand to you.

Every partner-facing endpoint, /v1/third-party/menu/, /v1/third-party/orders/*, /v1/third-party/hotels/*, and /v1/third-party/webhook/ , is authenticated with two headers instead of a bearer token:

X-API-Key: YOUR_API_KEY
X-API-Secret: YOUR_API_SECRET

The tenant is resolved entirely from this credential ,never send a tenant_id, restaurant_id, or hotel_id yourself.

Terminal window
curl https://api.restrolab.com/v1/third-party/menu/ \
-H "X-API-Key: YOUR_API_KEY" \
-H "X-API-Secret: YOUR_API_SECRET"
const response = await fetch('https://api.restrolab.com/v1/third-party/menu/', {
headers: {
'X-API-Key': 'YOUR_API_KEY',
'X-API-Secret': 'YOUR_API_SECRET',
},
});
import requests
response = requests.get(
"https://api.restrolab.com/v1/third-party/menu/",
headers={"X-API-Key": "YOUR_API_KEY", "X-API-Secret": "YOUR_API_SECRET"},
)

The owner controls the credential’s lifecycle from their RestroLab dashboard:

Action Endpoint Effect
Create POST /v1/third-party/credentials/ Issues a new api_key + api_secret, shown once.
Rotate POST /v1/third-party/credentials/{id}/rotate/ Issues a new api_secret, shown once. The api_key is unchanged, only the secret rotates, so you only need to update one value on your side. The previous secret stops working immediately; there is no grace period, so coordinate the rotation with a deploy on your end.
Revoke POST /v1/third-party/credentials/{id}/revoke/ Deactivates the credential.

If your platform’s requests suddenly start failing authentication, the most likely cause is that the owner rotated or revoked the credential, ask them to check their RestroLab integrations settings.

A single credential can be valid for the Restro module, the Hotel module, or both — independently:

  • A hotel-only tenant’s credential works against every /hotels/* endpoint and gets a 403 from every Restro endpoint (/menu/, /orders/*).
  • A restaurant-only tenant’s credential works the other way around.
  • A tenant with both enabled can use either set of endpoints through the same credential.

This is not a per-request authorization error,it reflects which modules the tenant has actually enabled, and won’t change until they enable the other module.

  • Never embed your X-API-Key / X-API-Secret in client-side code, mobile apps, or public repositories ,call this API from your own backend.
  • Send requests only over HTTPS.
  • Use a separate credential per tenant, and per environment where possible.
  • If a credential may have been exposed, ask the tenant owner to rotate it immediately from their RestroLab dashboard.
  • Store credentials in a secrets manager or environment variables, never in source control.
Status Meaning Response body
401 Unauthorized No credential, an unknown/inactive X-API-Key, or a wrong X-API-Secret. {"code": "invalid_credentials", "message": "Invalid integration credentials."}
403 Forbidden The credential is valid but the module you’re calling isn’t enabled for this tenant. {"code": "error", "message": "You do not have permission to perform this action."}see Feature gating above.

See Error Handling for the full error envelope and every status/code combination.