Appearance
Manifest reference
Every app is defined by its manifest — a JSON document you edit through the Developer panel. The manifest declares what your app does, what data it needs access to, and which optional surfaces it enables. Stayblox validates the manifest on every save and again at version submission.
Complete example
jsonc
{
"name": "Smart Lock Manager",
"description": "Automatically deliver access codes to guests at check-in.",
// Access scopes the host consents to at install.
"scopes": ["read_bookings", "read_contacts", "write_conversations"],
// Webhook topics to receive (must be covered by scopes).
"webhooks": {
"topics": ["booking.confirmed", "booking.cancelled", "booking.checked_in"]
},
// App-owned data fields on bookings, properties or contacts.
"metafields": [
{
"owner": "booking",
"key": "access_code",
"type": "string",
"visibility": "guest" // exposed to guests in emails + themes
},
{
"owner": "booking",
"key": "lock_battery_pct",
"type": "number",
"visibility": "host" // shown in the host panel "App data" section
}
],
// Per-install settings the host fills in during installation.
"settings_schema": [
{ "key": "api_key", "type": "string", "label": "Lock API key", "required": true },
{ "key": "default_code_length", "type": "number", "label": "Code length", "default": 6 }
],
// Embedded UI page rendered inside the host panel.
"app_page": {
"url": "https://app.smartlock.example/stayblox"
},
// OAuth redirect URIs for the "Connect your Stayblox account" flow.
"oauth": {
"redirect_uris": ["https://smartlock.example/auth/stayblox/callback"]
},
// HTML snippets injected into storefront slots.
"injections": [
{
"slot": "head",
"template": "<script src=\"https://cdn.smartlock.example/widget.js?key={{ api_key }}\"></script>"
}
]
}Keys
name
| Required | Type |
|---|---|
| Yes | string |
The display name shown to hosts in the marketplace and panel.
description
| Required | Type |
|---|---|
| No | string |
A short description of what your app does, shown in the marketplace listing.
scopes
| Required | Type |
|---|---|
| No | array of scope strings |
Access scopes the host consents to when installing. Stayblox checks the install's granted scopes on every API call and webhook delivery — not the manifest directly. See Scopes for the full catalog.
jsonc
"scopes": ["read_bookings", "read_contacts", "write_conversations"]Validation: every entry must be a known AppScope value; unknown strings are rejected. A webhook topic also requires its scope to be listed here.
webhooks
| Required | Type |
|---|---|
| No | object |
Topics you want delivered to the install's webhook endpoint.
jsonc
"webhooks": {
"topics": ["booking.confirmed", "booking.cancelled"]
}Validation: every topic must be a known WebhookTopic value, and its required scope must appear in scopes. See Webhooks for the full topic list.
metafields
| Required | Type |
|---|---|
| No | array of objects |
Declares app-owned data fields you intend to store on bookings, properties, or contacts. See Metafields for how to write and read these at runtime.
Each entry:
| Property | Required | Values | Description |
|---|---|---|---|
owner | Yes | booking | property | contact | The model this field attaches to. |
key | Yes | ^[a-z0-9_]{1,64}$ | Unique identifier for this field (snake_case, max 64 chars). |
type | Yes | string | number | boolean | date | The value's data type. Stored as text; the type is advisory for display. |
visibility | Yes | private | host | guest | Who sees the value (see below). |
Visibility:
| Value | Who sees it |
|---|---|
private | Only your app via the API. Never shown in the host panel or guest emails. |
host | Shown in the "App data" section on booking/property detail pages in the host panel. |
guest | Like host, plus exposed as variables in guest email templates and in the app_data(booking) Twig function for themes. |
Validation: owner must be booking, property, or contact; key must match ^[a-z0-9_]{1,64}$; type must be one of the four values above; visibility must be one of the three values above.
settings_schema
| Required | Type |
|---|---|
| No | array of objects |
Defines the per-install settings form shown to the host during installation and on the app's settings page. Values are stored on the install and passed to your server in session payloads (payment/channel protocols) and accessible via the settings object on the install's token context.
Each entry:
| Property | Required | Description |
|---|---|---|
key | Yes | string. Identifier for this setting. |
type | Yes | string, number, boolean, or select. |
label | Yes | Human-readable label shown in the form. |
required | No | boolean. Defaults to false. |
default | No | Default value shown pre-filled. |
options | For select | Array of { value, label } objects. |
The setting value is available in injections templates as (see below) and in session payloads under settings.key.
injections
| Required | Type |
|---|---|
| No | array of objects |
HTML snippets rendered into named slots in the storefront. Each entry defines where the snippet goes and what to render. See Injections for the full guide including slot names and template examples.
jsonc
"injections": [
{
"slot": "head",
"template": "<script src=\"https://cdn.example.com/widget.js?key={{ api_key }}\"></script>"
}
]Each entry:
| Property | Required | Description |
|---|---|---|
slot | Yes | The named storefront slot (e.g. head, body_end). |
template | Yes | Raw HTML. May contain placeholders interpolated from the install's settings at render time. |
Sanitization: injection templates are reviewed and sanitized as part of the app review process. Scripts must load from a fixed https:// origin; inline javascript: URIs and <script> blocks without a src are rejected.
app_page
| Required | Type |
|---|---|
| No | object |
Declares an embedded UI page rendered inside the host panel as a sandboxed iframe. See Embedded pages for the full JWT session and token-refresh protocol.
jsonc
"app_page": {
"url": "https://app.example.com/stayblox"
}| Property | Required | Description |
|---|---|---|
url | Yes | The https:// URL of your app page. The iframe loads {url}?session=<JWT>. |
Validation: must be a valid https:// URL.
oauth
| Required | Type |
|---|---|
| No | object |
Registers redirect URIs for the OAuth 2.0 authorization-code install flow. See OAuth install for the complete flow.
jsonc
"oauth": {
"redirect_uris": [
"https://app.example.com/auth/stayblox/callback"
]
}| Property | Required | Description |
|---|---|---|
redirect_uris | Yes | Array of https:// URIs. The redirect_uri parameter in an authorize request must exactly match one of these strings (no wildcards, no partial matches). |
Restriction: OAuth install is available for free and externally-billed apps only. Paid platform-billed apps install through the marketplace.
Validation: every URI must be a valid https:// URL.
payments
| Required | Type |
|---|---|
Required for type: payment | object |
Payment-protocol specifics: endpoints, capabilities, and currency support. See Payment apps for the full reference.
channel
| Required | Type |
|---|---|
Required for type: channel | object |
Channel-protocol specifics: ARI endpoints, supported OTA identifiers. See Channel managers for the full reference.
Validation rules summary
| Rule | Detail |
|---|---|
| Scope strings | Must be known AppScope values. |
| Webhook topics | Must be known WebhookTopic values; required scope must be listed. |
| All URLs | Must be valid https:// URLs (no http://, no IP addresses without explicit approval). |
oauth.redirect_uris | Exact-match strings — no wildcards, no trailing slashes unless registered with one. |
| Metafield owners | Must be booking, property, or contact. |
| Metafield keys | Must match ^[a-z0-9_]{1,64}$. |
| Metafield types | Must be string, number, boolean, or date. |
| Injection slots | Must be known storefront slot names. |
| Injection templates | Sanitized at review — only trusted https:// script/resource origins allowed. |
| Settings schema | Each entry must declare a string key and a string type. |
Validation runs on every partner save (showing errors inline) and again at version submission. Submitting with validation errors is blocked.