Graph cloud-communications answer returns HTTP 400 "The input was not valid." for ALL incoming Teams calls to our calling bot - even from the official Microsoft.Graph.Communications SDK

Zeev Russak 0 Reputation points
2026-11-11T15:59:41.6666667+00:00

Graph cloud-communications answer returns HTTP 400 "The input was not valid." for ALL incoming Teams calls to our calling bot — even from the official Microsoft.Graph.Communications SDK

We have a Teams calling bot (service-hosted media, Graph cloud-communications API) that stopped being able to answer calls. Every incoming call reaches our calling webhook correctly (Bot Framework service-auth validates, commsNotifications parse), but POST /communications/calls/{id}/answer is rejected with:


HTTP 400

{"error":{"code":"","message":"The input was not valid.","details":[{"code":"","message":"The input was not valid."}]}}

The Teams client then plays "You can't talk to this Bot just yet. But we are working on it." and the call terminates with resultInfo {code:408, subcode:8544, message:"Callee could not be reached."}. Teams retries ~3x with fresh call ids — every answer fails identically.

What we verified (this is NOT a client-code problem)

  • Body shape: docs-exact answer body with acceptedModalities: ["audio"] and mediaConfig: { "@odata.type": "#microsoft.graph.serviceHostedMediaConfig" } — with and without preFetchMedia. Also tried the fully-qualified bound-action path /microsoft.graph.answer (what the SDK sends on the wire).
  • The official SDK fails identically. We deployed a stateless bot using Microsoft.Graph.Communications 1.2.0.3742 (the SimpleIvrBot/VoiceRecorder pattern: NotificationProcessor + GraphAuthClient + answer via ServiceHostedMediaConfig) and drove real Teams calls into it: same 400, same message. Its own HTTP trace shows the correct URL, correct token, correct body.
  • Permissions: the bot app holds Calls.AccessMedia.All AND Calls.JoinGroupCall.All (application, admin-consented) — both verified present in the roles claim of the actual token used.
  • Correlation headers: X-Microsoft-Tenant, Scenario-Id, Client-Request-Id all sent (matching the SDK's HttpConstants).
  • Timing: answer lands ~2s after the incoming notification (15s window).
  • Notification delivery is healthy: incoming/established/terminated notifications arrive and validate against the api.aps.skype.com keys. The caller identity in the notification is plaintext (decrypted), ids in resource and resourceUrl match.

Registration resets — all failed

  • incomingCallRoute tried graphPma (default) and graph; toggled enableCalling off/on.
  • MsTeamsChannel ARM resource deleted and recreated with the same calling config.
  • The entire botServices resource deleted and recreated (same app id; normal bot messaging kept working throughout).
  • Service principal deleted and recreated (new object id), both Calls.* roles re-granted and re-consented.

Every time, the next call fails at answer with the same 400.

Notably: answering with a DIFFERENT app registration produces 403 code 7503 "Application is not registered in our store" — the store knows our app id and specifically refuses the answer for it. This is why we suspect the APS/calling-store agent record for our app id is corrupted, possibly since a teams app bot migrate from a Teams-managed bot to an Azure Bot on 2026-11-05.

Environment

  • Tenant: redacted for the public post — shared with Microsoft via the private support channel
  • App id: redacted for the public post (single-tenant, created 2026-10-11)
  • Azure Bot: a single Azure Bot resource (name/URL redacted), MsTeams channel: enableCalling=true, callingWebhook=<redacted https endpoint> (dedicated tunnel; notifications arrive fine), incomingCallRoute=graphPma
  • Notification partition observed: emea03 (region: emea)
  • Multiple failed call ids observed on 2026-11-10 (ids available privately)

Questions

  1. Is there a known issue with the calling store rejecting answer with an empty-code 400 for migrated bots?
  2. Can the APS agent registration for an app id be corrupted by teams app bot migrate, and can it be reset? Full resource recreations did not clear it.
  3. Is there any tenant-side remediation we have missed?

Happy to share full request/response captures, SDK HTTP traces, and reproduce on demand.

Azure AI Bot Service
Azure AI Bot Service

An Azure service that provides an integrated environment for bot development.

0 comments No comments

1 answer

Sort by: Most helpful
  1. AI answer

    2026-11-11T16:00:59.6+00:00

    The next action is to open a Microsoft support case for the Graph Cloud Communications/Teams calling backend and request investigation of the bot’s calling registration, because no public self-service command is documented for resetting an APS/calling-store agent record.

    What can be concluded

    • The documented answer operation accepts acceptedModalities and mediaConfig, requires application permission Calls.JoinGroupCall.All, and additionally requires Calls.AccessMedia.All only for application-hosted media. A successful request returns 202 Accepted; the answer must arrive within 15 seconds for a regular call.^1^
    • serviceHostedMediaConfig is a supported media configuration, and preFetchMedia is optional.^2^
    • Teams Developer CLI supports migrating bot registration between Teams and Azure, but its public documentation does not describe an APS reset, calling-store repair, or this failure mode.^3^
    • There is no cited Microsoft bulletin establishing that teams app bot migrate corrupts calling registration or that empty-code HTTP 400 responses are a recognized migration defect. The temporal association is therefore useful evidence for support, but not an established root cause.

    Your tests already eliminate the useful client-side branches: the documented payload, official communications SDK, token roles, timing, correlation headers, webhook processing, and resource/service-principal recreation all produce the same result. Repeating those operations is unlikely to add diagnostic value.

    One remaining configuration check

    Inspect the currently installed Teams app package, not only the source manifest, and verify that its bot entry has:

    {
      "bots": [{
        "botId": "<same Microsoft app ID used for Graph authentication>",
        "supportsCalling": true,
        "supportsVideo": false
      }]
    }
    

    Teams calling bots require supportsCalling, the Teams calling channel, Graph application permissions with admin consent, and the calling webhook configuration.^4^

    If the installed package already has the same app ID and supportsCalling: true, do not recreate or migrate it again. That leaves no documented tenant-side repair that would reset an internal calling agent record.

    Also note that chatInfo and meetingInfo can appear in an incoming group-call notification; they are not documented as fields that must be copied into the answer request body. The required answer-body fields are acceptedModalities and mediaConfig.^1^

    Escalation package

    Open the case from the affected tenant’s Microsoft 365 or Azure support channel and classify it under Microsoft Graph → Cloud Communications / Teams calling bot. Ask for escalation to the service team that owns calling-bot registration and APS routing.

    Attach:

    1. UTC timestamps for at least two failed calls.
    2. Call IDs and notification resource URLs.
    3. Graph response headers:
      • request-id
      • client-request-id
      • date
    4. Sanitized raw request and response, including the exact URL and body.
    5. Token claims relevant to diagnosis: aud, appid/azp, tid, and roles; omit the token itself.
    6. Incoming, established, and terminated notifications for the same call.
    7. The installed Teams manifest and the Azure Teams-channel configuration.
    8. CLI version, migration command output, and the migration timestamp.
    9. A before/after timeline showing that calling worked before migration and failed afterward, if logs establish that.
    10. The control test showing a different app ID receives 7503, while the affected app reaches a different validation path and receives the empty-code 400.

    Microsoft’s Graph debugging guidance specifically recommends logging a unique client-request-id and preserving the response request-id and date, because these values are needed for support correlation.^5^

    Use a direct request in the case attachment to avoid SDK abstraction:

    POST https://graph.microsoft.com/v1.0/communications/calls/{call-id}/answer
    Authorization: Bearer <redacted>
    Content-Type: application/json
    client-request-id: <unique-guid>
    
    {
      "acceptedModalities": ["audio"],
      "mediaConfig": {
        "@odata.type": "#microsoft.graph.serviceHostedMediaConfig"
      }
    }
    

    Request that support verify:

    • The app ID’s Teams calling-agent registration and routing state.
    • Whether both pre- and post-migration registrations exist.
    • Whether the notification-side agent and Graph answer authorization-side agent resolve to the same registration.
    • Whether the registration can be repaired or removed and reprovisioned internally.
    • Whether the failure correlates with a regional APS partition or active service incident.

    Before submitting, check tenant Service health and Message center for an active Teams or Microsoft Graph incident; those interfaces expose current and historical health for subscribed Microsoft services.^6^

    Avoid posting tenant IDs, app IDs, call IDs, tokens, or unredacted traces publicly; provide them only through the private support case.


    References

    1. call: answer - Microsoft Graph v1.0 | Microsoft Learn
    2. serviceHostedMediaConfig resource type
    3. Teams developer CLI
    4. Register calls and meetings bot for Microsoft Teams
    5. How to debug Microsoft Graph API calls
    6. Access service health and communications in Microsoft Graph
    AI-generated content may be incorrect. Read our transparency notes for more information.

    Was this answer helpful?

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.