# API quick start

Everything the dashboard does is available as a JSON REST API. Typical uses: create bookings from your PMS or booking engine, put the guest portal link into your own messages, read the online check-in data, or pull the MTA return into accounting.

The complete reference is at [/api/docs](/api/docs), machine-readable as [OpenAPI 3.1](/api/v1/openapi.json).

## 1. Create an API key

**Settings → API keys** (owners only): give the key a name and a **role**. The key can do exactly what that role can do — use *Viewer* for read-only integrations. The full key (`gpk_…`) is shown **once**; store it in your secret store. Revoke it there at any time.

![Settings → API keys](/site/img/docs/d-settings-apikeys.webp "Settings → API keys")

## 2. Make your first call

Send the key as a bearer token. The base URL is your portal address.

```
curl https://stay.example.com/api/v1/me \
  -H "Authorization: Bearer gpk_xxxxxxxxxxxx"
```

The answer tells you the tenant, the key's role and its permissions.

## 3. Create a booking

```
curl -X POST https://stay.example.com/api/v1/bookings \
  -H "Authorization: Bearer gpk_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "propertyId": "p_xxxxxxxxxx",
    "checkIn": "2026-11-18", "checkOut": "2026-11-23",
    "adults": 2, "children": 0,
    "guest": { "firstName": "Sofia", "lastName": "Rossi", "email": "sofia@example.com", "phone": "+39 333 1234567" },
    "source": "mypms", "externalId": "RES-48213",
    "sendPortalLink": true
  }'
```

- With `source` + `externalId` the call is an **upsert**: sending the same reservation again updates it instead of creating a duplicate.
- Overlapping dates return **409**; add `"allowOverlap": true` if that is intended.
- The response contains the booking with `portalUrl` — the guest's personal link.

Property IDs come from `GET /api/v1/properties`.

## 4. Read status and check-in data

- `GET /api/v1/bookings?from=2026-11-01&to=2026-11-30` — list with payment states (`eco.status`, `deposit.status`), `stayState` and `unlocked`.
- `GET /api/v1/bookings/{id}` — full booking incl. online check-in data and activity log.
- `GET /api/v1/bookings?format=csv` — spreadsheet export.

## 5. React to events

Instead of polling, register a webhook (**Settings → Webhooks**) and receive signed events such as `checkin.completed` or `payment.completed` — see [Webhooks](/docs/webhooks).

## Conventions

| Topic | Rule |
|---|---|
| Format | JSON in and out, UTF-8; dates `YYYY-MM-DD`, timestamps ISO 8601 UTC |
| Errors | HTTP status + `{ "error": "message" }` — 400 invalid input, 401 bad key, 403 not allowed, 404 not found, 409 conflict, 429 too many requests |
| Money | Decimal numbers in the account currency (EUR by default) |
| Secrets | Masked in responses; send an empty value to keep a stored secret |

## Frequently asked questions

### Is there a sandbox?

Use the [demo account](/demo) to explore, and Revolut's sandbox mode for payments. API keys can't be created in the demo — create a free account for development.

### Is there an API for platform operators?

Yes: the platform API (`/api/platform/v1`, keys starting with `gpp_`) provisions tenants and domains. See the platform section of the [API reference](/api/docs#platform).
