Skip to content
CloudOps
Newsletter
All guides
AI for Microsoft Teams By James Joyner IV · · 8 min read

Publishing Teams Apps: The Manifest and App Catalog Workflow

Your bot works in sideload but won't install for the team. The gap is the app manifest and the catalog approval flow — here's the path from dev to org-wide.

  • #microsoft-teams
  • #app-manifest
  • #publishing
  • #devops
  • #governance
  • #ci-cd

The most demoralizing moment in Teams development isn’t writing the bot — it’s the moment your perfectly working app, the one you’ve been debugging via sideload for two weeks, refuses to install for anyone but you. Sideloading hides the entire distribution story, and that story is the app manifest plus the catalog approval flow. Get it wrong and your app is a personal toy; get it right and it’s installable org-wide with a click.

I’ve shipped enough internal DevOps apps to know exactly where the snags are. Here’s the path from “works on my machine” to “available in the company app catalog.”

The manifest is the contract

manifest.json is the single source of truth for what your app is and what it’s allowed to do. Teams reads it at install time to decide what surfaces to show and what permissions to request. The fields that matter most for distribution:

{
  "manifestVersion": "1.17",
  "id": "00000000-0000-0000-0000-000000000000",
  "version": "1.4.0",
  "developer": {
    "name": "Platform Team",
    "websiteUrl": "https://ops.example.com",
    "privacyUrl": "https://ops.example.com/privacy",
    "termsOfUseUrl": "https://ops.example.com/terms"
  },
  "name": { "short": "DeployBot", "full": "DevOps DeployBot" },
  "description": {
    "short": "Deploy and status via ChatOps",
    "full": "Guarded deploys, rollbacks, and live status inside Teams."
  },
  "icons": { "color": "color.png", "outline": "outline.png" },
  "accentColor": "#1F6FEB",
  "bots": [{ "botId": "BOT-APP-ID", "scopes": ["team", "groupChat"] }],
  "validDomains": ["ops.example.com"],
  "webApplicationInfo": {
    "id": "AAD-APP-ID",
    "resource": "api://ops.example.com/AAD-APP-ID"
  }
}

The fields that bite people:

  • validDomains — if your tab or dialog loads a URL whose domain isn’t listed here, it renders blank with no error. Every domain your app navigates to must be here.
  • id — the Teams app ID, distinct from your bot ID and your Azure AD app ID. Three different GUIDs; mixing them up is the classic confusion.
  • developer URLs — privacy and terms URLs are required for catalog submission. Missing them passes sideload and fails publish.
  • Icons — you need a 192×192 color icon and a transparent 32×32 outline icon. Wrong dimensions fail validation silently in some clients.

Validate before you ever try to publish

Run validation locally so you find schema errors at your desk, not in an admin’s rejection email:

teamsapp validate --manifest-path ./appPackage/manifest.json
# or use the App Validation tool in Developer Portal

The Developer Portal (dev.teams.microsoft.com) has a more thorough checker that flags the soft requirements — accessibility, metadata completeness — that the schema validator misses but the store reviewers don’t.

Three distribution paths

There isn’t one “publish” — there are three, and you pick by audience:

  1. Sideload (upload a custom app) — you, or anyone with permission, manually uploads the app package zip. Dev and small-team use. Requires custom app upload to be enabled in your tenant.
  2. Org app catalog — submit the package to your organization’s catalog. A Teams admin reviews and approves it, after which everyone in the org can install it from the “Built for your org” section. This is the path for internal DevOps tools.
  3. Microsoft Teams Store — public submission with Microsoft’s full certification review. Only relevant if you’re shipping to other companies.

For an internal deploy bot, you want path 2.

The org catalog flow

The package you submit is a zip of exactly three files: manifest.json, color.png, outline.png. Nothing else. Then:

teamsapp publish --env prod
# pushes the package to the org catalog, pending admin approval

Or upload the zip in the Teams admin center under Teams apps → Manage apps → Upload new app. An admin reviews it, approves it, and can pin it or pre-install it for specific groups. The admin also controls app permission policies — even an approved app won’t appear for users whose policy blocks it, which is a common “approved but invisible” head-scratcher.

Versioning and updates

Updating a published app is just a new package with a bumped version (semver), re-submitted. Two rules that save pain:

  • Bump version on every change or Teams won’t recognize the update and users keep the old app.
  • Never change id for an update. A new id is a brand-new app, not an update — your users would have both installed. The id is the app’s identity for its entire life.

If your update adds new permissions or RSC scopes, it triggers admin re-consent. Plan for that: a permission change is not a silent update, and users may need to re-accept.

Wire it into CI

Because the package is deterministic and teamsapp publish is scriptable, app distribution belongs in your release pipeline alongside the service deploy. A merge to main builds the service, builds the app package with the prod manifest, and submits to the catalog. The only manual step left is the admin approval — which is exactly the human gate you want for something that installs org-wide.

The manifest is small but unforgiving: every URL declared, three GUIDs kept straight, required developer fields present, version bumped. Get those right and the distribution story that sideloading hides becomes a one-command publish.

For more on shipping DevOps apps in Teams, see the Microsoft Teams guides, and the prompt library has prompts for generating and validating manifests.

Manifest schema versions, required fields, and admin center flows change over time. Validate against the current schema and Developer Portal before submitting to your catalog.

Free download · 368-page PDF

Download the Free 500-Prompt DevOps AI Toolkit

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.