Skip to content

Configuration (app.toml)

app.toml is the config file for your app. The CLI reads it when you run app push, app validate, or any command that needs the app slug. Edit it locally and push; do not edit it through a panel.

What is not in app.toml: the app icon, store listing (description, gallery, pricing, and category), and media assets for public apps. Those are managed in the Account-panel Dashboard. For icon specs and how to change it, see App icon.

Complete example

toml
name = "Smart Lock Manager"
type = "remote"                # "remote" | "payment" | "channel" | "injection"
distribution = "public"        # "private" | "public"
slug = "smart-lock-manager"    # public: set before first push; private: server-generated

scopes = ["read_bookings", "read_contacts", "write_conversations"]
capabilities = []
webhooks = ["booking.confirmed", "booking.cancelled", "booking.checked_in"]
webhook_url = "https://app.smartlock.example/webhooks/stayblox"

[oauth]
redirect_uris = ["https://smartlock.example/auth/stayblox/callback"]

[app_page]
url = "https://app.smartlock.example/stayblox"

[[settings_schema]]
key = "api_key"
type = "string"
label = "Lock API key"
required = true

[[settings_schema]]
key = "default_code_length"
type = "number"
label = "Code length"
default = 6

[[metafields]]
owner = "booking"
key = "access_code"
type = "string"
visibility = "guest"

[[metafields]]
owner = "booking"
key = "lock_battery_pct"
type = "number"
visibility = "host"

[[injections]]
slot = "head"
template = '<script src="https://cdn.smartlock.example/widget.js?key={{ api_key }}"></script>'

Keys

name

RequiredType
Yesstring

The display name shown to hosts in the marketplace and panel.


type

RequiredTypeDefault
Yesstringremote

The app type. One of remote, payment, channel, or injection. Private apps support remote only.


distribution

RequiredTypeDefault
Yesstringpublic

private or public. Cannot be changed after the first push. See App lifecycle.


slug

RequiredType
Required for publicstring

A globally unique, URL-safe identifier for the app.

  • Public apps: choose a slug and set it before the first push.
  • Private apps: omit slug; the server generates one on the first push and the CLI writes it back to app.toml.

Format: ^[a-z0-9][a-z0-9-]{1,39}$ (lowercase letters, digits, and hyphens; must start with a letter or digit).


scopes

RequiredType
Noarray of strings

Access scopes the host consents to when installing. Stayblox checks the install's granted_scopes on every API call and webhook delivery. See Scopes for the full catalog.

toml
scopes = ["read_bookings", "read_contacts", "write_conversations"]

Validation: every entry must be a known scope value. A webhook topic also requires its scope to be listed here.


capabilities

RequiredType
Noarray of strings

Privileged behaviors the app requests, separate from data-access scopes. The host grants these at install time.

ValueWhat it enables
act_as_assignment_providerReceive task assignment requests and write back the chosen assignee.
register_task_typesAdd custom task types with their own fields and checklists.

See Assignment provider apps and Tasks.


webhooks

RequiredType
Noarray of strings

Topics delivered to webhook_url for each install. See Webhooks for the generated topic list.

toml
webhooks = ["booking.confirmed", "booking.cancelled"]

Validation: every topic must be a known value, and its required scope must appear in scopes.


webhook_url

RequiredType
Nostring

The HTTPS URL Stayblox delivers webhook events to. Copied onto each install at install time. Stayblox signs every delivery with a per-install webhook_secret issued at app install. See Signing & security.

toml
webhook_url = "https://app.example.com/webhooks/stayblox"

Validation: must be a valid https:// URL.


[oauth]

RequiredType
Notable

Registers redirect URIs for the OAuth 2.0 authorization-code install flow. See OAuth install for the complete flow.

toml
[oauth]
redirect_uris = ["https://app.example.com/auth/stayblox/callback"]
PropertyRequiredDescription
redirect_urisYesArray of https:// URIs. The redirect_uri in an authorize request must exactly match one; no wildcards, no partial matches.

Validation: every URI must be a valid https:// URL.

Private apps: [oauth] is not supported for private apps.


[app_page]

RequiredType
Notable

Declares an embedded UI page rendered inside the host panel as a sandboxed iframe. See Embedded pages for the JWT session protocol.

toml
[app_page]
url = "https://app.example.com/stayblox"
PropertyRequiredDescription
urlYesThe https:// URL of your app page. The iframe loads {url}?session=<JWT>.

Validation: url must be a valid https:// URL.

Private apps: [app_page] is not supported for private apps.


[[settings_schema]]

RequiredType
Noarray of tables

Defines the per-install settings form shown to the host at install time and on the app settings page. Each entry is a field definition.

PropertyRequiredTypeDescription
keyYesstringIdentifier for the setting.
typeYesstringstring, number, boolean, or select.
labelYesstringHuman-readable label shown in the form.
requiredNobooleanDefaults to false.
defaultNoanyDefault value shown pre-filled.
optionsFor selectarrayArray of { value, label } objects.

Setting values are available in [[injections]] templates as and in protocol payloads under settings.key.

Private apps: [[settings_schema]] is not supported for private apps.


[[injections]]

RequiredType
Noarray of tables

HTML snippets rendered into named slots in the storefront. See Injections for slot names and template examples.

toml
[[injections]]
slot = "head"
template = '<script src="https://cdn.example.com/widget.js?key={{ api_key }}"></script>'
PropertyRequiredDescription
slotYesNamed storefront slot (e.g. head, body_end).
templateYesRaw HTML. May use placeholders interpolated from the install's settings.

Sanitization: injection templates are reviewed as part of the app review. Scripts must load from a fixed https:// origin; inline scripts are rejected.

Private apps: [[injections]] is not supported for private apps.


[[metafields]]

RequiredType
Noarray of tables

Declares app-owned data fields stored on bookings, properties, or contacts. See Metafields for how to write and read them at runtime.

PropertyRequiredValuesDescription
ownerYesbooking | property | contactThe model this field attaches to.
keyYes^[a-z0-9_]{1,64}$Unique identifier for this field (snake_case, max 64 chars).
typeYesstring | number | boolean | dateValue data type.
visibilityYesprivate | host | guestWho can see the value.

Visibility:

ValueWho sees it
privateYour app only, via the API. Never shown in the host panel or guest emails.
hostShown in the host panel on booking, property, or contact detail pages.
guestLike host, plus exposed in guest email templates and in app_data(booking) in themes.

Private apps: [[metafields]] is not supported for private apps.


Distribution-aware validation

The CLI sends your distribution value with the manifest. The server validates accordingly.

CheckPrivatePublic
type: remote onlyRequiredAny type allowed
[oauth], [app_page], [[settings_schema]], [[injections]], [[metafields]]Not supportedSupported
SlugServer-generated (written back on first push)Required; ^[a-z0-9][a-z0-9-]{1,39}$
Scope and topic validationSame as publicSame as private

channels

RequiredType
Noarray of objects

Declares the messaging channels this app provides. Requires the provide_inbox_channel scope in scopes and a valid endpoints.message_send URL. See Inbox channel-provider apps for the full protocol reference.

jsonc
"channels": [
  {
    "key": "whatsapp",
    "name": "WhatsApp",
    "caps": {
      "richText": false,
      "quickReplies": false,
      "outboundWindowHours": 24,
      "templateRequiredOutsideWindow": true
    }
  }
]
PropertyRequiredDescription
keyYesUnique lowercase slug, ^[a-z0-9_]{2,40}$. Values email, web_form, and web are reserved.
nameNoDisplay name shown to hosts in the inbox UI. 2 to 60 characters. When omitted, the key is prettified ("sample_chat" renders as "Sample chat").
caps.outboundWindowHoursYesHours after the last inbound message during which free-form replies are allowed.
caps.richTextNoChannel supports bold, links, etc. Defaults to false.
caps.quickRepliesNoChannel supports quick-reply buttons. Defaults to false.
caps.templateRequiredOutsideWindowNoAn approved template is required outside the outbound window. Defaults to false.

endpoints

RequiredType
Noobject

HTTPS endpoint URLs Stayblox calls on your server for protocol-based interactions.

PropertyRequired whenDescription
message_sendchannels is declaredStayblox POSTs outbound host messages here, signed with HMAC. See Inbox channel-provider apps.
ari_pushprovide_channel is in scopesStayblox POSTs rate/availability/restriction pushes here, signed with HMAC. See Channel apps.
toml
scopes = ["provide_channel", "read_properties", "read_rates"]

[endpoints]
ari_push = "https://app.example.com/stayblox/ari-push"

Validation: the provide_channel scope requires endpoints.ari_push to be a valid https:// URL.

type = "channel"

A channel app implements the ARI push and reservation-ingestion protocol described in Channel apps. It needs provide_channel in scopes and endpoints.ari_push set; most channel apps also request read_properties and read_rates to discover inventory and back-fill rates, and subscribe to property.updated to re-sync listing content. A channel app may also provide guest messaging on the same install by additionally declaring provide_inbox_channel, channels, and endpoints.message_send.


Validation rules summary

RuleDetail
Scope stringsMust be known scope values.
Webhook topicsMust be known topic values; required scope must be listed.
webhook_urlMust be a valid https:// URL.
All URLsMust be valid https:// URLs (no http://).
oauth.redirect_urisExact-match strings; no wildcards, no trailing slashes unless registered with one.
Metafield ownersMust be booking, property, or contact.
Metafield keysMust match ^[a-z0-9_]{1,64}$.
Metafield typesMust be string, number, boolean, or date.
Injection slotsMust be known storefront slot names.
Injection templatesSanitized at review; only trusted https:// script origins allowed.
endpoints.ari_pushRequired and must be a valid https:// URL when provide_channel is in scopes.
Settings schemaEach entry must declare a string key and a string type.

Validation runs on every app validate and app push. Errors are shown inline; pushing with errors is blocked.


See also: Scopes reference · Webhook topics · GraphQL reference

© Stayblox — Developer Platform