Back to blog

Microsoft Teams Form Notifications for Enterprise Laravel Apps

Manuk Minasyan · · 7 min read

The first time a head of engineering at a 600-person company told me "we cannot install Slack, IT has standardized on Teams," I assumed they were exaggerating. They weren't. Microsoft 365 is the stack — Outlook, SharePoint, Intune, Defender, Purview — and Teams is where the workday lives. Slack and Discord are not approved tools and never will be. So when somebody on the Laravel side wants form submissions to ping a channel, the only acceptable target is a Teams channel.

This post is the 2026 recipe. I want to date it on the page because the Teams webhook story has been a moving target. The pattern most older Laravel tutorials show — Http::post() to a URL on outlook.office.com/webhook/... — has been deprecated by Microsoft and is being retired through 2025 and 2026. New tenants cannot create those connectors at all. If you copy that snippet today, it works for the demo and breaks for the customer. The teams notification laravel recipe below assumes you are starting fresh in mid-2026, on a tenant where the only path Microsoft still ships is Power Automate Workflows. This pairs naturally with the internal IT request pattern, which is the other half of the same enterprise need.

Two paths in 2026: Workflows or legacy connectors

There is one Microsoft-recommended path and one legacy path, and they are not interchangeable. Build against the recommended one.

Power Automate Workflow Legacy Incoming Webhook
Status in 2026 Recommended path Retiring; new ones blocked
URL host *.webhook.office.com *.outlook.office.com
Payload format Adaptive Card (attachment envelope) MessageCard or Adaptive Card
Who can create Channel owner or member (workflow owner) Channel admin via connector — disabled for new connectors in most tenants
Lifetime risk Active investment End-of-life with extended dates

The Workflows path is the "When a Teams webhook request is received" trigger, exposed through the Workflows app in Teams and powered by Power Automate. The legacy path is the old Office 365 Connector, which Microsoft has been retiring through a series of extended deadlines. New connectors cannot be created in most tenants, and existing ones are on a published end-of-life schedule. If your form posts to outlook.office.com, that integration has an expiration date. Build against the Workflows trigger.

For readers comparing platforms before they commit: the Slack-side version of this story is shorter, simpler, and stable, but the choice is usually not yours.

Setting up a Power Automate workflow

The setup happens inside Teams, not the Azure portal — which is the first thing nobody mentions. In Teams, find the channel you want submissions to land in, click the ... next to the channel name, and pick Workflows. Search for the template Post to a channel when a webhook request is received. Pick the team and channel, name the flow something boring like "FilaForms — Demo form submissions," and save. Teams will hand back a URL on the *.webhook.office.com host. Copy it.

Two things to know before you paste that URL into a config file. First: in some tenants, IT has disabled the Workflows app for non-admin users, and you'll get a "this app is not approved" wall instead of a setup screen. That is the real friction at enterprises — a Jira ticket to IT, sometimes a week. Worth raising up-front in the meeting where this integration is scoped.

Second: the workflow has a single owner, and that owner is you. If you leave the company without adding a co-owner, the flow becomes orphaned and stops posting. Add a co-owner the same day you create it. Microsoft has an "orphan flows" management story for admins, but the cleanest fix is to never get there.

How to send Laravel form submissions to a Microsoft Teams channel in 2026

To send Laravel form submissions to a Microsoft Teams channel in 2026, create a Power Automate Workflow in the target channel, copy its webhook URL, and POST an Adaptive Card payload from a queued Laravel listener whenever a form is submitted. Four steps:

  1. In Teams, create a "Post to a channel when a webhook request is received" workflow on the channel.
  2. Copy the generated *.webhook.office.com URL into config/services.php.
  3. Listen for FormSubmitted in a queued Laravel listener.
  4. POST an Adaptive Card payload to the workflow URL.

In FilaForms terms, that means a listener on the FormSubmitted event, queued so a slow Microsoft hop never blocks the form response, sitting on top of the outgoing webhook layer FilaForms already ships. The shape of the listener:

class PostFormSubmissionToTeams implements ShouldQueue
{
    public function handle(FormSubmitted $event): void
    {
        $url = config('services.teams.workflow_url');

        Http::acceptJson()
            ->retry(3, 500)
            ->post($url, $this->adaptiveCardPayload($event->submission));
    }
}

Three things to notice. The URL is in config, not hardcoded. The HTTP client retries on transient failures because Microsoft does throttle. And the payload is built by a dedicated method, because the Adaptive Card shape is verbose enough to deserve isolation.

Adaptive Card basics for the form submission payload

The teams adaptive card form payload is a typed envelope around a card body. The outer object declares type: message with an attachments array, each attachment carries a contentType of application/vnd.microsoft.card.adaptive, and the inner content is the actual card — title, body rows, optional actions. The $schema and version fields belong on the inner card, not the envelope. Version 1.4 is a safe choice in mid-2026 — earlier versions miss layout elements you'll want, later ones outpace Teams' rendering.

A workable shape:

{
  "type": "message",
  "attachments": [{
    "contentType": "application/vnd.microsoft.card.adaptive",
    "content": {
      "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
      "type": "AdaptiveCard",
      "version": "1.4",
      "body": [
        { "type": "TextBlock", "text": "New demo form submission", "weight": "Bolder", "size": "Medium" },
        { "type": "FactSet", "facts": [
          { "title": "Name", "value": "Jane Doe" },
          { "title": "Company", "value": "Acme Corp" }
        ]}
      ]
    }
  }]
}

FactSet is the workhorse for form submissions — it renders field/value rows that look native in Teams. Add an Action.OpenUrl pointing at the submission in your FilaForms admin if you want a one-click way for the recipient to drill in.

Edge cases at enterprise scale

The friction at enterprises is not technical, it's organizational. Tenant admin policy decides whether your developers can create Workflows at all — if not, you need an IT ticket and a sponsor. Plan around that calendar, not around the hour the integration takes to build.

The technical limits are gentler than they read. Message payloads are capped at 28 KB, which is plenty for any reasonable form submission card. The trigger is rate-limited at four requests per second per workflow — a problem if you're piping form submissions from a viral campaign, fine for internal forms. Your queued listener with retries will absorb the occasional 429 without anyone noticing.

What we got wrong

We shipped the first Teams integration in late 2024 against the Incoming Webhook connector because the docs example was thirty lines of Http::post() and the URL worked the first time. Three months later Microsoft announced the connector retirement, the timeline kept getting extended, and every enterprise customer asked the same question — is this still going to work next year. The honest answer was no. Rebuilt against the Workflows trigger, ate the migration, sent a heads-up email to every customer using the old path, and the lesson stuck. Bet on what the vendor is shipping, not what the vendor is documenting. Microsoft is shipping Power Automate. Connectors are paperwork.

Closing

If you're building toward a Teams target and your form layer doesn't yet have a way out, you can set up FilaForms here and point a queued listener at the workflow URL. The IT request use case is the most common pairing — the form, the queue, the channel notification.

External references: Microsoft's retirement of Microsoft 365 connectors, the current Teams incoming webhook documentation, and the Adaptive Cards documentation hub.

Related posts