Using Graph API to create Teams 1:1 chat and send message via app (not user)

Haraldur Blöndal Kristjansson 0 Reputation points

I am looking to create a notification application which the company will use for e.g. reminders or incidents. The goal is to send the messages to 1:1 chat in Teams and I have already:

  • Registered the app in MS Entra
  • Gotten the following Graph API permissions:

|Chat.Create|Application|Create chats|Yes||| |Chat.ReadWrite.All|Application|Read and write all chat messages|Yes||| |ChatMessage.Send|Delegated|Send user chat messages|No||| |User.Read|Delegated|Sign in and read user profile|No||| |User.ReadBasic.All|Application|Read all users' basic profiles|Yes||

I have put together some Java code but to be able to create a chat (which is implied possible by the Chat.create permission for an Application ) I am having problem with what ID I can use for the application? It seems like it is limited to user:user but not user:application, but according to Application should be able to send to user in Teams.

  public String createChat(String usersId) throws Exception {
      String accessToken = getAccessToken();
      HttpClient client = HttpClient.newHttpClient();
      String payload = GraphApiHelper.createChatPayload(usersId);
      HttpRequest request = HttpRequest.newBuilder()
              .header("Content-Type", "application/json")
              .header("Authorization", "Bearer " + accessToken)
      HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
      System.out.println("Chat create Response body: " + response.body());
      return extractChatIdFromResponse(response.body());
  public static String createChatPayload(String userId) {
      String appId = "PLACEHOLDER_FOR_QUESTION";
      Map<String, Object> member1 = Map.of(
              "@odata.type", "#microsoft.graph.aadUserConversationMember",
              "roles", List.of("owner"),
              "user@odata.bind", "'" + userId + "')"
      Map<String, Object> member2 = Map.of(
              "@odata.type", "#microsoft.graph.aadUserConversationMember",
              "roles", List.of("owner"),
              "user@odata.bind", "'" + appId + "')"
      Map<String, Object> chat = Map.of(
              "chatType", "oneOnOne",
              "members", List.of(member1, member2)
      return createJsonPayload(chat);
  Chat create Response body: {"error":{"code":"Forbidden","message":"AclCheckFailed","innerError":{"code":"40400","message":"RosterCreationNotAllowed-Create Thread: One or more members cannot be added to the unique roster thread","date":"2024-03-27T09:04:40","request-id":"XXXXXXXXX","client-request-id":"XXXXXXXXXXXXX"}}}

The above works fine if I replace the appID with user id of another user in Teams.

Microsoft Teams
Microsoft Teams
A Microsoft customizable chat-based workspace.
9,034 questions
Microsoft Graph
Microsoft Graph
A Microsoft programmability model that exposes REST APIs and client libraries to access data on Microsoft 365 services.
10,530 questions
{count} votes