Declare how COHO talks to your process. Runtime paths are relative to your
registered base URL. Browser-facing paths are relative to
config.browserBaseUrl when supplied.
{ "manifestVersion": 1, "health": { "path": "/health", "method": "GET" }, "config": { "mode": "native+embedded+external", "browserBaseUrl": null, "externalConfigureUrl": "/configure", "schemaPath": "/config/schema", "getPath": "/config", "putPath": "/config", "quickViewPath": "/ui", "openPresentation": "modal" }, "requestedCapabilities": ["conversations.read", "conversations.write"], "triggers": { "lifecycle": { "setupPath": "/webhooks/atrium/setup", "disconnectPath": "/webhooks/atrium/disconnect" }, "schedules": [], "events": [ { "key": "tenancy.started", "path": "/webhooks/atrium/triggers/event" } ] }, "operations": [ { "name": "list", "path": "/operations/list", "method": "GET", "description": "List records for the organisation", "effect": "read" } ]}This sample is a web app (quick view). That is the default for almost every product. Match samples/hello-node/manifest.example.json (or hello-python / hello-go / hello-dotnet in atrium-app-samples). Starter manifests may still say "mode": "both" — that is the legacy spelling of native + external for the same web-app surface; "native+embedded+external" here is the explicit form. Do not start from a null quickViewPath unless you have confirmed a true background agent — then use samples/hello-agent-node and read its README (§6).
| Field | Meaning |
|---|---|
health.path |
Unsigned GET. See §4. |
triggers.lifecycle.setupPath |
Signed POST on connect. Must return 2xx or connect rolls back. |
triggers.lifecycle.disconnectPath |
Signed POST after credentials are revoked (best-effort). Delete org-scoped data. |
triggers.schedules |
Opt-in. Empty = COHO will not tick you on a cron. Each entry: key, cron (5-field: minute hour day-of-month month day-of-week; *, lists, ranges, steps), timezone (IANA, default UTC), path. Private / unreviewed apps: at most 4 schedules, and no denser than hourly (minute field must be a single value). Reviewed public listings are not capped this way. |
triggers.events |
Opt-in. Unknown keys are ignored until COHO supports them. |
requestedCapabilities |
Catalogue scope ids the app requires (e.g. conversations.write). Legacy short names still expand. Connect fails if the connecting person cannot grant every resolved scope. See §8. |
operations |
Optional. Named endpoints COHO may call on your app through the app-operations gateway (Public API + MCP). See §3.5. Omit or [] when unused. |
runtimeEnv |
Optional. Declared Hosting runtime env keys: [{ "name", "secret", "description", "required" }]. Values are set via the runtime-env API, not in the manifest. Required keys must be set before a Ready hosted app re-provisions. See Runtime secrets (Hosting). |
config.schemaPath / getPath / putPath |
Optional app-owned light prefs only (a handful of scalars). Store proxies signed GET/PUT. Omit when unused. Serious UI is quick view, not this form. |
config.browserBaseUrl |
Public HTTPS origin for hosted app UI. Runtime webhooks and config remain on the private registered base URL. |
config.externalConfigureUrl |
Optional new-tab configure path on the browser base URL. |
config.quickViewPath |
In-COHO iframe path. Default for almost all apps. Omit only for rare background agents (webhooks + API + optional light prefs). See §6. |
config.openPresentation |
When quickViewPath is set: full | modal | side. Store defaults to modal if omitted. |
config.mode is one or more of native, external, embedded, joined with + when combined (for example native+embedded). The legacy value both means native + external.
Browser URLs are HTTPS only in non-local environments. Self-host runtime base URLs are also HTTPS; COHO Hosting may mint a private HTTP runtime base URL inside the VPC.