Microsoft Teams incoming webhook 400 "Bad payload" in CI
A Teams incoming webhook returns HTTP 400 with "Bad payload received by generic incoming webhook." when the body is not a shape it accepts. The connector expects a MessageCard (or, for Workflows, an Adaptive Card wrapped in an attachment), not an arbitrary JSON object.
What this error means
The Teams notify step gets HTTP 400 and the text "Bad payload received by generic incoming webhook." No card appears in the channel.
< HTTP/1.1 400 Bad Request
Bad payload received by generic incoming webhook.Common causes
The JSON is not a MessageCard
Sending {"text":"..."} (Slack-style) to a Teams connector fails; Teams needs @type: MessageCard with @context and a text field, or an Adaptive Card for Workflows.
Unescaped values broke the JSON
A commit message with a quote or newline interpolated into the card body produces invalid JSON that Teams rejects.
How to fix it
Send a valid MessageCard
- Wrap the message in a MessageCard with
@typeand@context. - Encode interpolated text so the JSON stays valid.
- POST the card as the body.
msg="$(git log -1 --pretty=%s)"
payload=$(jq -n --arg t "$msg" '{
"@type":"MessageCard","@context":"http://schema.org/extensions",
"summary":"CI","text":$t}')
curl -sS -X POST -H 'Content-Type: application/json' \
--data "$payload" "$TEAMS_WEBHOOK_URL"Use an Adaptive Card for Workflows URLs
Power Automate Workflows endpoints expect an attachment with an Adaptive Card, not a MessageCard.
{"type":"message","attachments":[{"contentType":"application/vnd.microsoft.card.adaptive","content":{"type":"AdaptiveCard","version":"1.4","body":[{"type":"TextBlock","text":"build passed"}]}}]}How to prevent it
- Match the payload shape to the endpoint type (connector vs Workflows).
- Encode interpolated CI values with jq.
- Include a
summaryfield so the card renders in notifications.