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.
Partner authentication (everything else)
Section titled “Partner authentication (everything else)”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_KEYX-API-Secret: YOUR_API_SECRETThe tenant is resolved entirely from this credential ,never send a tenant_id, restaurant_id, or hotel_id yourself.
Example request
Section titled “Example request”curl https://api.restrolab.com/v1/third-party/menu/ \ -H "X-API-Key: YOUR_API_KEY" \ -H "X-API-Secret: YOUR_API_SECRET"JavaScript
Section titled “JavaScript”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', },});Python
Section titled “Python”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"},)Credential lifecycle
Section titled “Credential lifecycle”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.
Feature gating (why you might get a 403)
Section titled “Feature gating (why you might get a 403)”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 a403from 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.
Security recommendations
Section titled “Security recommendations”- Never embed your
X-API-Key/X-API-Secretin 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.
Common authentication errors
Section titled “Common authentication errors”| 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.
