Experimental Go library for building and validating Microsoft Adaptive Cards.
This project is experimental and not production-ready.
- API and behavior can change without notice.
- Breaking changes are expected.
- The implementation is not at 100% Microsoft Adaptive Cards feature parity.
- Use with caution, especially in production systems.
This repository provides:
- Strongly typed Go models for selected Adaptive Card features
- Builder-style APIs for composing cards
- Logical validation and JSON Schema validation support against schema version 1.5.0
- JSON factory-based decoding for interface fields (
Element,Action) - Optional, SSRF-hardened webhook posting helper for Teams/workflow endpoints
- Microsoft Teams
msteamshost extension support (for example full-width cards)
- Go 1.25 or newer (see
go.mod)
go get github.com/untcha/go-adaptivecardsFull API documentation is available on pkg.go.dev.
Quick "Hello, World!" example (from examples/simple/main.go):
package main
import (
"context"
"fmt"
"os"
"github.com/untcha/go-adaptivecards/adaptivecards/card"
"github.com/untcha/go-adaptivecards/adaptivecards/elements"
"github.com/untcha/go-adaptivecards/adaptivecards/webhook"
)
func main() {
// Webhook URL
url := os.Getenv("TEAMS_TEST_WORKFLOW_URL")
textblock := elements.NewTextBlock("Hello, World!")
card, err := card.NewCard().
AddElement(textblock).
Build()
if err != nil {
panic(err)
}
// Validate runs logical checks and validates against the embedded
// Adaptive Cards JSON Schema before the card is sent or serialized.
if err := card.Validate(); err != nil {
panic(err)
}
json, _ := card.MarshalJSON()
fmt.Println(string(json))
// Post to Teams webhook if URL is provided
if url != "" {
if err := webhook.PostToWorkflowRaw(context.Background(), url, card); err != nil {
panic(err)
}
}
}Runnable examples live under examples/:
examples/simple— minimal "Hello, World!" card.examples/simple_table— aTablewith columns, header row, styling, and an action.examples/full_width— a full-width card using the Teamsmsteamshost extension.
Each example optionally posts to a Teams workflow when the
TEAMS_TEST_WORKFLOW_URL environment variable is set.
Legend:
[x]Type/feature exists in this repo[ ]Not implemented yet- Checked items can still be partial vs full official schema behavior
-
AdaptiveCard -
body -
actions -
selectAction -
backgroundImage -
minHeight -
rtl -
lang -
speak -
fallbackText -
verticalContentAlignment -
refresh(placeholder only) -
authentication(placeholder only) -
metadata(placeholder only)
-
Action.OpenUrl -
Action.Submit -
Action.ToggleVisibility -
Action.ShowCard -
Action.Execute
-
TextBlock -
RichTextBlock -
TextRun -
Image -
Media
-
Container -
Column -
ColumnSet -
ActionSet -
FactSet -
ImageSet -
Table(includingTableRow,TableCell,TableColumnDefinition)
-
Input.Text -
Input.Number -
Input.Date -
Input.Time -
Input.ChoiceSet -
Input.Toggle
- Microsoft Teams
msteams(full-width viaCard.SetFullWidth,Card.SetMSTeams)
- Logical validation methods on card/types
- JSON factory decode for action/element interfaces
- Embedded Adaptive Card schema validation support
- Webhook helper (
webhook.PostToWorkflowRaw) with SSRF-hardened URL policy
adaptivecards/card: AdaptiveCard root model and card-level builders/validationadaptivecards/actions: action types and action factoryadaptivecards/elements: leaf elements and element validationadaptivecards/containers: container-style elements, including Tableadaptivecards/inputs: input elements and validationadaptivecards/core/model: shared enums, value objects, low-level validationadaptivecards/core/element: element interfaces, fallback model, element factoryadaptivecards/schema: schema validation integrationadaptivecards/webhook: helpers to send card JSON to webhook endpoints
webhook.PostToWorkflowRaw validates the card and posts it as the entire
request body to a workflow/webhook endpoint:
err := webhook.PostToWorkflowRaw(ctx, workflowURL, card)Outbound requests are guarded by a URLPolicy that is strict by default to
reduce SSRF risk: HTTPS only, private/loopback/link-local targets blocked, and
an optional exact-hostname allowlist. Use
webhook.PostToWorkflowRawWithClientAndPolicy to supply a custom
*http.Client and/or relax the policy.
Common commands:
task test
task lint
task check
task project:update:schemaThe root Taskfile.yml includes the shared Go-library tasks from
taskfiles/common.yml (flattened, so they run unprefixed, e.g. task lint).
Repo-specific tasks live in taskfiles/Taskfile.project.yml and are included
under the project: namespace (e.g. task project:update:schema).
Notable changes are documented in CHANGELOG.md, following Keep a Changelog and Semantic Versioning.
This project is licensed under the MIT License - see the LICENSE file for details.
