Skip to content

Management API

The Management API (/dev/*) is the REST surface you call as a developer to author and manage your apps. It is separate from the runtime Developer GraphQL API: the GraphQL API is what your running app server calls during normal operation; the Management API is what you (and the CLI) call to create, update, and inspect apps.

The stayblox CLI wraps every endpoint here. You only need to call the API directly for CI pipelines, scripted automation, or custom tooling.

Slug-only identifiers. The Management API, CLI, and webhook envelope identify a team by its slug (X-Stayblox-Team: <slug>, --team <slug>) and an app by its app.toml slug. Sequential numeric team or install ids never appear here. Per-resource object ids inside event payloads (booking id, contact id, ...) are unaffected.

Authentication

The Management API uses a personal access token (PAT) that you mint in the Account panel under Developer access tokens. Tokens are per-user, named, and revocable. The plain text is shown once on creation.

bash
stayblox login --token <your-account-pat>

The CLI stores the token in ~/.config/stayblox/config.json. Every Management API request carries it as a bearer token:

Authorization: Bearer <account-pat>

The token must have the develop-apps ability, which is granted to tokens created on the Developer access tokens page. The token identifies your account; the team is chosen per request via the X-Stayblox-Team header on the endpoints that need it.

See Getting started for the full auth walkthrough.

Base URL

https://api.stayblox.com/api/dev/

Team-scoped requests

Some endpoints act on a specific team install. Those require:

X-Stayblox-Team: <team-slug>

where <team-slug> is the slug for the team you want to act on (for example, 8cs3o-qe). Fetch the slugs your account has access to from GET /dev/teams. The CLI resolves --team <slug> to this header automatically.

Endpoints that do not require a team header are account-scoped and operate across all teams.

Endpoint reference

Account-scoped endpoints

These endpoints do not require X-Stayblox-Team.


GET /dev/teams

Lists the teams your account has developer access to. Use this to discover your team slugs.

Response:

json
{
  "data": [
    { "slug": "8cs3o-qe", "name": "Ocean View Apartments" },
    { "slug": "4rk7p-wm", "name": "City Loft Rentals" }
  ]
}

GET /dev/apps

Lists all apps owned by your account.

Response:

json
{
  "data": [
    {
      "slug": "rate-sync",
      "name": "Rate Sync",
      "type": "remote",
      "distribution": "private",
      "status": "active",
      "live_version": 3,
      "install_count": 2
    }
  ]
}

POST /dev/apps/validate

Validates an app.toml config payload without creating or updating anything. Run this as a CI step before push.

Request body (application/json):

json
{
  "distribution": "private",
  "manifest": {
    "name": "Rate Sync",
    "type": "remote",
    "scopes": ["read_rates", "write_rates"],
    "webhooks": ["rates.updated"],
    "webhook_url": "https://rate-sync.example/webhooks/stayblox"
  }
}

Always returns HTTP 200. An invalid config is valid: false with error details.

Response:

json
{ "valid": true, "errors": [] }

On invalid config:

json
{ "valid": false, "errors": ["webhook_url must be a valid https:// URL."] }

POST /dev/apps

Pushes a new version of your app (or creates the app if it does not exist). Equivalent to stayblox app push.

The request body contains the parsed fields from your app.toml plus a manifest object holding the runtime config:

Request body (application/json):

json
{
  "name": "Rate Sync",
  "type": "remote",
  "distribution": "private",
  "slug": "rate-sync",
  "manifest": {
    "scopes": ["read_rates", "write_rates"],
    "webhooks": ["rates.updated"],
    "webhook_url": "https://rate-sync.example/webhooks/stayblox"
  },
  "release": true
}

Set release: false to create a version without releasing it immediately (equivalent to app push --no-release).

Response (HTTP 201):

json
{
  "slug": "rate-sync",
  "name": "Rate Sync",
  "type": "remote",
  "distribution": "private",
  "status": "active",
  "live_version": 1,
  "install_count": 0
}

For private apps, if slug is omitted, the server generates one and the CLI writes it back to app.toml.


GET /dev/apps/{slug}

Returns the current state of an app.

Response:

json
{
  "slug": "rate-sync",
  "name": "Rate Sync",
  "type": "remote",
  "distribution": "private",
  "status": "active",
  "live_version": 3,
  "install_count": 2
}

GET /dev/apps/{slug}/versions

Lists all versions of an app, newest first.

Response:

json
{
  "data": [
    {
      "id": 3,
      "status": "approved",
      "live": true,
      "scope_escalation": false,
      "created_at": "2026-06-28T10:00:00Z"
    },
    {
      "id": 2,
      "status": "approved",
      "live": false,
      "scope_escalation": false,
      "created_at": "2026-06-20T08:00:00Z"
    }
  ]
}

live: true marks the version currently serving installs.


POST /dev/apps/{slug}/release

Releases a version to live. Equivalent to stayblox app release.

Request body (application/json):

json
{ "version": 2 }

Omit version to release the latest draft. Pass a specific version id to roll back to an earlier approved version (see App lifecycle).

Response:

json
{
  "version": 2,
  "status": "approved",
  "live": true
}

GET /dev/apps/{slug}/installs

Lists all installs of the app across every team in your account.

Response:

json
{
  "data": [
    { "team": "8cs3o-qe", "is_active": true, "is_dev_install": false },
    { "team": "4rk7p-wm", "is_active": true, "is_dev_install": true }
  ]
}

is_dev_install: true marks an install created with app install --dev for local webhook forwarding.


Team-scoped endpoints

These endpoints require X-Stayblox-Team: <slug>.


POST /dev/apps/{slug}/installs

Installs the app on a team. Equivalent to stayblox app install --team <slug>. This is the step that issues the per-install runtime token and webhook secret for the install.

Headers: X-Stayblox-Team: <slug>

Response (HTTP 201):

json
{
  "team": "8cs3o-qe",
  "token": "stayblox_app_...",
  "webhook_secret": "whsec_..."
}

Copy both values now. The token is shown once and is the bearer credential your app server uses on every GraphQL request. The webhook_secret is the per-install HMAC key for verifying Stayblox callbacks; it is not independently rotatable. Rotating the runtime token requires an explicit call to /dev/apps/{slug}/installs/token.


DELETE /dev/apps/{slug}/installs

Uninstalls the app from a team. Equivalent to stayblox app uninstall --team <slug>.

Headers: X-Stayblox-Team: <slug>

Response:

json
{ "message": "Uninstalled." }

POST /dev/apps/{slug}/installs/token

Rotates the install's runtime token. The old token stops working immediately. Equivalent to stayblox app token --team <slug>.

Headers: X-Stayblox-Team: <slug>

Response:

json
{ "token": "stayblox_app_..." }

The new token is shown once.


GET /dev/apps/{slug}/forward

Drain endpoint for the local webhook forwarding loop. Equivalent to stayblox app forward --team <slug>. See Stayblox CLI for the forwarding protocol.

Headers: X-Stayblox-Team: <slug>

Response:

json
{
  "data": [
    {
      "event_id": "01J9...",
      "body": "{\"event_id\":\"01J9...\",\"topic\":\"booking.confirmed\",...}",
      "headers": {
        "X-Stayblox-Topic": "booking.confirmed",
        "X-Stayblox-Signature": "sha256=...",
        "X-Stayblox-Timestamp": "1719576131"
      }
    }
  ]
}

Each poll extends the forwarding TTL by 60 seconds. When the CLI stops polling, the TTL lapses and the platform resumes normal delivery automatically.


GET /dev/apps/{slug}/deliveries

Retrieves the webhook delivery log for the install on the specified team (up to 100 entries, newest first).

Headers: X-Stayblox-Team: <slug>

Response:

json
{
  "data": [
    {
      "event_id": "01J9...",
      "topic": "rates.updated",
      "status": "delivered",
      "attempts": 1,
      "delivered_at": "2026-06-28T12:00:00Z"
    }
  ]
}

GET /dev/apps/{slug}/deliveries/{eventId}

Returns the full signed request for one delivery. The body and headers are exactly what Stayblox sent (or would send). Use this to replay a specific delivery to your local server; see stayblox app replay in Stayblox CLI.

Headers: X-Stayblox-Team: <slug>

Response:

json
{
  "event_id": "01J9...",
  "body": "{\"event_id\":\"01J9...\",\"topic\":\"booking.confirmed\",...}",
  "headers": {
    "X-Stayblox-Topic": "booking.confirmed",
    "X-Stayblox-Signature": "sha256=...",
    "X-Stayblox-Timestamp": "1719576131"
  }
}

App configuration

Your app is configured through app.toml, not the panel. See Configuration (app.toml) for every key. The CLI sends the parsed app.toml to POST /dev/apps on each app push.

© Stayblox — Developer Platform