Founding keys are opena year free at 6,000 req/hour, for the first 1,000 developersClaim yours
Documentation 29

Microsoft Teams API quickstart · 3 min read

The same story, in Graph's dialect.

The Microsoft Teams surface of Microsoft Graph v1.0 — teams, channels, messages, replies, members, and the tenant's users — over the same simulated data set the Slack host serves. Byte-identical message text, one canonical story: the incident-bridge burst brackets a real tracker incident, review threads echo real PRs, release announcements cite fetchable tags.

01Point your client at graph.
02Walk teams → channels → messages
03Pin a snapshot for CI

01 / Base URL + auth

A Graph tenant, any token.

Point requests at https://graph.sandboxapis.dev — clients target graph.microsoft.com, so graph. is the drop-in prefix (teams.sandboxapis.dev aliases the same host). Paths are Graph's own: /v1.0/… with OData query parameters and @odata.nextLink paging. Auth is a Bearer token — real Graph wants an Entra JWT; here any value passes, but the header must be present: its absence answers Graph's real 401 (InvalidAuthenticationToken), exactly as captured live.

request.sh
curl -H 'Authorization: Bearer any-token' \
  "https://graph.sandboxapis.dev/v1.0/me/joinedTeams"

Using a key? Keys & rate limits → — a SandboxAPIs key rides the same Bearer slot and lifts the anonymous limit.

02 / The reads that matter

Teams, channels, messages, people.

report.sh
# The teams the service identity belongs to — one per engineering team,
# plus the org-wide team holding #agora, #incident-bridge, and #releases
curl -H 'Authorization: Bearer any-token' "https://graph.sandboxapis.dev/v1.0/me/joinedTeams"

# A team's channels
curl -H 'Authorization: Bearer any-token' \
  "https://graph.sandboxapis.dev/v1.0/teams/TEAM_ID/channels"

# Channel messages (default 20 per page; walk @odata.nextLink)
curl -H 'Authorization: Bearer any-token' \
  "https://graph.sandboxapis.dev/v1.0/teams/TEAM_ID/channels/CHANNEL_ID/messages"

# A thread's replies, newest first
curl -H 'Authorization: Bearer any-token' \
  "https://graph.sandboxapis.dev/v1.0/teams/TEAM_ID/channels/CHANNEL_ID/messages/MESSAGE_ID/replies"

# The tenant's users — emails join against every other host's rosters
curl -H 'Authorization: Bearer any-token' "https://graph.sandboxapis.dev/v1.0/users?$top=10"

03 / A real response

Live from the incident bridge.

200 · application/json
{
  "@odata.context": "https://graph.sandboxapis.dev/v1.0/$metadata#teams('31837fb8-c814-42ba-8775-01dedad6c921')/channels('19%3Ae5b377c202622bec6934aec07c160755%40thread.tacv2')/messages",
  "@odata.count": 1,
  "value": [
    {
      "id": "1781455608488",
      "replyToId": null,
      "etag": "1781455608488",
      "messageType": "message",
      "createdDateTime": "2026-06-14T16:46:48.488Z",
      "lastModifiedDateTime": "2026-06-14T16:46:48.488Z",
      "lastEditedDateTime": null,
      "deletedDateTime": null,
      "subject": null,
      "summary": null,
      "chatId": null,
      "importance": "normal",
      "locale": "en-us",
      "webUrl": "https://teams.microsoft.com/l/message/19%3Ae5b377c202622bec6934aec07c160755%40thread.tacv2/1781455608488?groupId=31837fb8-c814-42ba-8775-01dedad6c921&tenantId=e4de0213-744a-45dd-8ffe-e7b19441c4d6&createdTime=1781455608488&parentMessageId=1781455608488",
      "policyViolation": null,
      "eventDetail": null,
      "from": {
        "application": null,
        "device": null,
        "user": {
          "id": "bd041599-64ea-45fb-8aaf-fac798df2d3a",
          "displayName": "Cassandra",
          "userIdentityType": "aadUser"
        }
      },
      "body": {
        "contentType": "text",
        "content": "schema marks a nullable field as required. paging whoever's closest to the logger."
      },
      "channelIdentity": {
        "teamId": "31837fb8-c814-42ba-8775-01dedad6c921",
        "channelId": "19:e5b377c202622bec6934aec07c160755@thread.tacv2"
      },
      "attachments": [],
      "mentions": [],
      "reactions": [],
      "messageHistory": []
    }
  ]
}

04 / Pin a snapshot

Deterministic CI.

The *.snap. base URL is byte-identical on every request — and teams-v1 shares its recipe with slack-2026-08, so a pinned cross-dialect messaging fixture is one artifact, not two universes.

.env
# reproducible in CI
export GRAPH_BASE_URL=https://teams-v1.snap.sandboxapis.dev/v1.0/

Tour the universe → · Coverage manifest → · Versioning & pinning →