aethexDocs
Microsoft Teams Phone logo
Telephony

Microsoft Teams Phone

Bring your own Microsoft Teams phone number and let an Aethex voice agent answer and place calls on it. You link your Teams tenant once with admin consent, attach an existing number to an agent, and the number stays in your own Microsoft 365 account.

How it works

Aethex connects to Microsoft Teams Phone over Azure Communication Services. You keep your number in your own Microsoft 365 tenant. Aethex never buys or ports it. A Teams administrator grants Aethex access to your tenant, you link a Teams resource account that carries one of your existing numbers, and you attach that number to an agent. From then on, inbound calls to the number are answered by the agent, and you can place outbound calls through the same API. The agent runs on Aethex's self-hosted speech-to-text, language model, and text-to-speech pipeline.

Note
You bring the number. It stays in your Microsoft 365 tenant, assigned to a Teams resource account you control. Connecting to Aethex never transfers ownership.
BEFORE YOU START

Prerequisites

In your Microsoft 365 tenant you need: a Teams Phone licence (the standalone SKU is Teams Phone Standard; Microsoft 365 E5 includes it); a phone number on a Teams resource account, which carries the free Microsoft Teams Phone Resource Account licence instead, never Teams Phone Standard, which Microsoft does not support on a resource account; and a Teams or Global administrator to grant consent and run one Teams PowerShell command. For outbound calls from your own number, the resource account additionally needs a Pay-As-You-Go Calling Plan licence assigned to it, plus a funding source: either Communications Credits, or Phone services consumption switched on for that plan under Billing → Your products in the Microsoft 365 admin centre. A Direct Routing number needs neither. Since 1 November 2025 a Calling Plan on its own covers inbound only. On the Aethex side: an API key with the msteams:read and msteams:write scopes, and an agent to answer calls (create one from the dashboard or the Agents API).

The Microsoft-side setup, in the order that works

What your Teams administrator does (once)

Everything below happens once, in your own Microsoft 365 tenant. Aethex never buys, ports or holds your number, and your Teams users are unaffected: the agent answers on a resource account, which is a licensed identity for voice apps rather than a person.1. Licence the tenant. You need Teams Phone (standalone or via E5). For the agent to place outbound calls you also need a Pay-As-You-Go Calling Plan for your zone, plus a funding source: either turn on Phone services consumption for that plan under Billing → Your products, or buy Communications Credits and keep a positive balance. Since 1 November 2025 a Calling Plan on its own covers inbound only.2. Buy the free resource-account licence. Marketplace → All products → Microsoft Teams Phone Resource Account. It costs nothing, but you must still place the order.3. Get a service number. Teams admin centre → Voice → Phone numbers → Add. Choose a Service number, not a User (subscriber) number: a resource account cannot hold a user number. You will be asked for an emergency address in the same country as the number.4. Create the resource account with the PowerShell command Aethex gives you (see the next section). The Teams admin centre cannot do this step, because the account has to be created against the Aethex application id.5. Licence the resource account: the free Teams Phone Resource Account licence, plus the Pay-As-You-Go Calling Plan if it will dial out. Set its usage location to the number's country. Do not give it Teams Phone Standard: Microsoft does not support that on a resource account and it stops the account working.6. Assign the number and link it to Aethex, then approve the consent link. Both are single commands or a single click, and both are covered in the next section.

Note
Licences take a few minutes to reach the resource account. If assigning the number fails with a licence error, wait and retry rather than changing anything.
END TO END · 6 STEPS

Connect your Teams number

The whole flow runs through the REST API plus one admin consent click and one PowerShell command. Set AETHEX_API_KEY in your shell, then work through the steps in order.

Tip
Outbound calls dial from the Teams number attached to the agent, placed on behalf of your resource account, so the recipient sees your own number. If an agent has no number attached yet, outbound falls back to a managed Aethex number. The connect + attach steps are also what route inbound calls on your own number to an agent.
  1. Get an API key with Teams scopes

    Create an API key that carries the msteams:read and msteams:write scopes. New keys include both by default, so a freshly created key works as-is. Export it as AETHEX_API_KEY for the calls below.

  2. Start admin consent

    Call POST /connect. It returns a consent_url and state_expires_in (seconds). Send your Teams or Global administrator to the consent_url, where they sign in to Microsoft and approve Aethex's access. The link is single-use and expires when state_expires_in elapses. After approval, Microsoft shows a short confirmation page they can close, and the connection is recorded against your tenant. Aethex stores only your Microsoft tenant id, never a password or secret.

    Begin the connection
    bash
    curl -X POST https://api.aethexai.com/api/v1/integrations/telephony/msteams/connect \
      -H "X-API-Key: $AETHEX_API_KEY"
    
    # Response: send your Teams admin to consent_url; it is valid for state_expires_in seconds.
    # {
    #   "consent_url": "https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize?client_id=...&state=...",
    #   "state_expires_in": 600
    # }
  3. Link a Teams resource account

    Call GET /resource-accounts to read connect_command, a ready-to-run Microsoft Teams PowerShell line. Your Teams administrator runs it once to create a resource account linked to Aethex, then assigns one of your existing Teams numbers to that account in the Teams Admin Center. Two details Microsoft enforces: the resource account must carry the free Microsoft Teams Phone Resource Account licence, never Teams Phone Standard, which is unsupported on resource accounts and breaks them; and the number must be a service number, not a user (subscriber) number. The ApplicationId and AcsResourceId in the command arrive pre-filled, so copy the string verbatim and only replace YOUR-TEAMS-DOMAIN with your tenant domain.

    Read and run the connect command
    bash
    # 1. Read the ready-to-run PowerShell line from your connection.
    curl https://api.aethexai.com/api/v1/integrations/telephony/msteams/resource-accounts \
      -H "X-API-Key: $AETHEX_API_KEY"
    
    # 2. In an elevated Microsoft Teams PowerShell session, paste the "connect_command"
    #    string exactly as returned (ApplicationId and AcsResourceId arrive filled in),
    #    replacing YOUR-TEAMS-DOMAIN with your tenant domain:
    Connect-MicrosoftTeams
    $ra = New-CsOnlineApplicationInstance \
      -UserPrincipalName '[email protected]' \
      -ApplicationId '<application-id>' -DisplayName 'Aethex Voice'
    Set-CsOnlineApplicationInstance -Identity '[email protected]' \
      -ApplicationId '<application-id>' -AcsResourceId '<acs-resource-id>'
    Sync-CsOnlineApplicationInstance -ObjectId $ra.ObjectId -ApplicationId '<application-id>'
    
    # 3. In the Teams Admin Center, assign one of your existing Teams SERVICE numbers
    #    (licensed with the free Teams Phone Resource Account SKU, never Teams Phone Standard) to that resource account.
  4. Confirm the number is linked

    Call GET /resource-accounts again. Once Microsoft finishes provisioning (usually a few minutes), the account appears with its assigned phone_number in E.164. Note the account's id, which you pass to attach in the next step.

    Resource account with its number
    json
    {
      "resource_accounts": [
        {
          "id": "6c7d8e9f-0a1b-2c3d-4e5f-60718293a4b5",
          "user_principal_name": "[email protected]",
          "display_name": "Aethex Voice",
          "phone_number": "+14155550100"
        }
      ],
      "connect_command": "Connect-MicrosoftTeams; $ra = New-CsOnlineApplicationInstance ..."
    }
  5. Attach the number to an agent

    Call POST /attach with the resource account id and the agent_id that should answer the number. Aethex authorizes the number into its calling resource and routes inbound calls to your agent. Re-attaching the same number just re-points it at a different agent.

    Bind the number to an agent
    bash
    curl -X POST https://api.aethexai.com/api/v1/integrations/telephony/msteams/attach \
      -H "X-API-Key: $AETHEX_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "resource_account_id": "6c7d8e9f-0a1b-2c3d-4e5f-60718293a4b5",
        "agent_id": "8a1b2c3d-4e5f-6789-abcd-ef0123456789",
        "friendly_name": "Support line"
      }'
  6. Place and receive calls

    Inbound calls to the attached number now reach the agent automatically, with no further setup. To dial out, call POST /calls with an agent_id and a destination to_number. The response returns a call_connection_id you can use to correlate the call.

    Place an outbound call
    bash
    curl -X POST https://api.aethexai.com/api/v1/integrations/telephony/msteams/calls \
      -H "X-API-Key: $AETHEX_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "agent_id": "8a1b2c3d-4e5f-6789-abcd-ef0123456789",
        "to_number": "+14155550123"
      }'

Authentication and scopes

Authenticate every request with your API key in the X-API-Key header. The Microsoft Teams endpoints require two scopes: msteams:read to view the connection and list resource accounts, and msteams:write to connect, attach a number, place a call, and disconnect. Both are part of the default scope bundle, so newly created keys already carry them. See Scopes for the full model.

Note
A key missing the required scope gets 403 Forbidden. Mint a new key or widen an existing one to include msteams:read and msteams:write.

Inbound and outbound calls

Inbound: once a number is attached, calls to it are answered by the agent you bound it to. Outbound: POST /calls rings the destination and bridges the callee into the agent's voice pipeline. Outbound calls are billed like any other Aethex call and go through the same admission checks, so a hard billing block or a capacity limit is reported before the call is placed.

Tip
Outbound calls are placed on behalf of the agent's attached Teams resource account, so the recipient sees your own number. An agent with no Teams number attached falls back to a managed Aethex number.

Common errors

The Teams endpoints return standard HTTP status codes. These are the ones you are most likely to hit; the API reference lists the errors per endpoint.

404Not connected

You called a Teams endpoint before completing admin consent, so there is no connection on your tenant yet.

Run POST /connect and have your Teams admin approve the consent_url first.

409Reconnect required

Your Microsoft session expired or the stored authorization is no longer valid, so Aethex can't read your resource accounts.

Call POST /connect again and re-approve. It silently refreshes the connection.

409Number unavailable

The resource account has no phone number assigned yet, or the number is already connected to another Aethex account.

Assign a number to the resource account in the Teams Admin Center, or release it from the other account before attaching it.

402Payment required

Outbound calling is blocked because the account has a hard billing block (for example, no credits or no payment method).

Resolve the balance or payment method in the billing dashboard, then retry POST /calls.

429At capacity

The voice backends are momentarily saturated, so a new outbound call couldn't reserve a slot.

Retry with backoff. Sustained 429s mean you should contact us to raise capacity.

503Temporarily unavailable

Microsoft Teams Phone isn't enabled on this deployment, or a required Microsoft service is momentarily unavailable.

Retry shortly. If it persists, contact [email protected].

The failures real tenants hit, and what each one means

If something does not work

Signing in to Teams PowerShell fails with `AADSTS530035`. Your tenant blocks the device-code sign-in flow, usually because security defaults are switched on. The Teams PowerShell module falls back to device code on macOS and Linux, so run it from Windows, which uses a different flow, or temporarily turn security defaults off, wait about fifteen minutes for the change to take effect, sign in, then turn them back on."You can't assign licenses that contain these conflicting services." You have Teams Phone Standard ticked alongside the Resource Account licence. Untick Teams Phone Standard.The number will not assign to the resource account. Either the licences have not propagated yet, or the number is a User number rather than a Service number. Only service numbers can be assigned to a resource account.Inbound works but outbound calls fail. The resource account is missing the Pay-As-You-Go Calling Plan licence, or the tenant has no funding source. Check that the plan is assigned to the resource account itself, and that Phone services consumption is on or Communications Credits have a positive balance.Callers hear that the number is unavailable. The resource account is not yet fully linked. Re-run the link and sync commands from the previous section, and confirm the account shows a phone number and Enterprise Voice enabled.

API reference

For every endpoint, parameter, and response field, see the Microsoft Teams Phone API reference.