Azure Communications Gateway Provisioning API

Azure Communications Gateway's Provisioning API for telecommunications operators allows you to provision the details of your customers and the numbers assigned to them into Azure Communications Gateway.

Provisioning customer and number information into Azure Communications Gateway is mandatory when using Azure Communications Gateway for Microsoft Teams Direct Routing and Zoom Phone Cloud Peering It's optional for Operator Connect, but allows you to configure a custom SIP header for billing.

You can't use the Provisioning API for Teams Phone Mobile numbers.

Getting started

Prerequisites

  • A tenant with the Azure Communications Gateway application deployed.
  • The fully qualified domain name (FQDN) for the Azure Communications Gateway that you would like to send queries to, as displayed on the Overview page for the resource in the Azure portal. The API is available on port 443 of the provapi subdomain of this domain (provapi.<base-domain>:443).
  • A machine with an IP address that allows access to the API, as configured in an allowlist as part of deploying Azure Communications Gateway.

Authentication and authorization

The Provisioning API uses OAuth 2.0 to control access to resources. The client application must obtain a valid authentication bearer token to access the Provisioning API. The bearer token indicates that the application is authorized for one or more of the scopes (roles) for the Provisioning API. We recommend using the client credentials flow (designed for a server-side process).

The following scopes are available for the Provisioning API:

  • ProvisioningAPI.Admin: Ability to invoke any operation across the API.
  • ProvisioningAPI.Read: Ability to invoke any read (GET) operation across the API.
  • ProvisioningAPI.Write: Ability to invoke any write (PUT, PATCH) operation across the API.
  • ProvisioningAPI.Delete: Ability to invoke any delete (DELETE) operation across the API.

To set up a client credentials flow:

  1. Ensure your application can support the client credentials flow.
    • When your application requests a token for the Provisioning API, it must use the following fields.

      Parameter Condition Description
      tenant required The directory tenant containing the Azure Communications Gateway, in guid or domain-name form.
      scope required The scope of authorization against the Azure Communications Gateway resource ID. For the client credentials flow described here, the scope should be https://func-voiceservice-rp-prod-eastuseuap.azurewebsites.net/.default.
      client_id required The application (client) ID assigned to your app.
    • The roles claim in the received token specifies the roles (scopes) that the client application is authorized to access.

    • Requests to the Azure Communications Gateway Provisioning Platform must have an Authorization header with this bearer token.

    • See the client credentials flow documentation for examples of using tokens.

  2. Use the Azure portal to register the application in the same tenant as your Azure Communications Gateway deployment. See Quickstart: Register an app in the Microsoft identity platform - Microsoft Entra | Microsoft Learn.
  3. Assign yourself as an owner for the app registration. See Assign application owner.
  4. Configure the app registration created by registering the application with app roles that use the scopes for the Provisioning API, as described earlier.
  5. As an administrator for the tenant, allow the application to use the app roles that you assigned. See Grant admin consent.

The Provisioning API uses standard Microsoft chains of trust for security certificates.

Key concepts

The Azure Communications Gateway Provisioning Platform allows you to provision numbers for use with services like Microsoft Teams Direct Routing or Zoom Provider Exchange. The Provisioning Platform has two key resources that you can control: accounts and numbers.

  • Account resources are descriptions of your customers (typically, an enterprise), and per-customer settings for service provisioning.
  • Number resources belong to an account. They describe telephone numbers (TNs), the services that the numbers make use of (for example, Microsoft Teams Direct Routing), and any extra per-number configuration.

For example, to provide Microsoft Teams Direct Routing service to a customer, Contoso, create an account resource with the Provisioning API for Contoso. The account contains configuration for Direct Routing (for example, a subdomain and corresponding tokens, needed to set up DNS records that Microsoft Teams can use to validate the customer's configuration). You must then add number resources to the account, and enable each number for Direct Routing. Zoom Phone Cloud Peering also requires account and number resources, but Zoom accounts don't contain the same configuration for subdomain and corresponding tokens.

Important

You must enable service on both the account and numbers within the account.

Examples

The following examples show sample requests for creating and managing accounts and numbers.

Create an account to represent a customer

Use PUT on the accounts/<accountName> endpoint to create an account named contoso for the customer Contoso and configure one or more communications services for the account. Use an If-None-Match header to verify that an account resource with this name doesn't already exist.

In the following example:

  • Direct Routing is configured.
  • Caller ID screening is enabled (the default).
  • The subdomain for the customer is contoso.
  • The customer-provided DNS TXT values needed to set up DNS records are in the region1Token and region2Token fields.

Request:

PUT /accounts/contoso?api-version=2023-10-01 HTTP/1.1

If-None-Match: *
Content-Type: application/json

{
  "directRouting": {
    "callScreening": true,
    "subdomain": "contoso",
    "subdomainTokens": {
      "region1Token": "exampleToken1",
      "region2Token": "exampleToken2"
    }
  }
}

Response:

HTTP/1.1 201 Created

{
  "name": "contoso",
  "details": {
    "directRouting": {
      "callScreening": true,
      "subdomain": "contoso",
      "subdomainTokens": {
        "region1Token": "exampleToken1",
        "region2Token": "exampleToken2"
      }
    }
  },
  "etag": "\"0000241f-0000-0700-0000-650845140000\""
}

View the details of the account

Use GET on the accounts/<accountName> endpoint to get the details of the account and check that setting up DNS records for the configured subdomain succeeded (only required for Microsoft Teams Direct Routing). The response includes the following fields:

  • directRoutingProvisioningState, representing the state of the DNS records. This field is included when the query parameter ?status=true is specified in the request, and is only relevant for Direct Routing.
  • All configuration previously set (or the default, if a field wasn't set).
  • An ETag representing the current state of the account. You can use the value in an If-Match header on subsequent update requests to ensure you don't overwrite changes made by another API users.

Request:

GET /accounts/contoso?api-version=2023-10-01&status=true HTTP/1.1

Response:

HTTP/1.1 200 OK

ETag: "0000241f-0000-0700-0000-650845140000"

{
  "directRoutingProvisioningState": {
    "subdomainStatus": "Provisioned"
  },
  "name": "contoso",
  "details": {
    "directRouting": {
      "callScreening": true,
      "subdomain": "contoso",
      "subdomainTokens": {
        "region1Token": "exampleToken1",
        "region2Token": "exampleToken2"
      }
    }
  },
  "etag": "\"0000241f-0000-0700-0000-650845140000\""
}

Update the configuration for the account

Use PUT on the accounts/<accountName> endpoint to update the configuration for the account. To ensure that the update doesn't overwrite a change made by another user, add an If-Match header with the ETag from the most recent response for the account.

Request:

PUT /accounts/contoso?api-version=2023-10-01 HTTP/1.1

If-Match: "0000241f-0000-0700-0000-650845140000"
Content-Type: application/json

{
  "directRouting": {
    "callScreening": false,
    "subdomain": "contoso",
    "subdomainTokens": {
      "region1Token": "exampleTokenNew1",
      "region2Token": "exampleTokenNew2"
    }
  }
}

Response:

HTTP/1.1 200 OK

{
  "name": "contoso",
  "details": {
    "directRouting": {
      "callScreening": false,
      "subdomain": "contoso",
      "subdomainTokens": {
        "region1Token": "exampleTokenNew1",
        "region2Token": "exampleTokenNew2"
      }
    }
  },
  "etag": "\"0000351f-0000-0700-0000-65084a810000\""
}

Add one number to the account

Use PUT on the account/<accountName>/numbers/<phoneNumber> endpoint to add an E.164 number to the account, enable one or more communications services and add any extra configuration. The chosen communications services must also be configured on the account. Use an If-None-Match header to verify that a number resource with this number doesn't already exist.

In the following example:

  • The number is +123451.
  • Direct Routing is enabled.
  • customSipHeader specifies that Azure Communications Gateway should add a header with the value exampleHeaderContents to messages sent to your network.

Important

The name of the custom header is set in the Azure portal configuration for the Provisioning API. It is the same for all messages.

PUT /account/contoso/numbers/%2B123451?api-version=2023-10-01 HTTP/1.1

If-None-Match: *
Content-Type: application/json

{
  "services": {
    "teamsDrEnabled": true,
    "teamsOcEnabled": false,
    "zoomEnabled": false
  },
  "configuration": {
    "customSipHeader": "exampleHeaderContents"
  }
}

Response:

HTTP/1.1 201 Created

{
  "phoneNumber": "+123451",
  "accountName": "contoso",
  "details": {
    "services": {
      "teamsDrEnabled": true,
      "teamsOcEnabled": false,
      "zoomEnabled": false
    },
    "configuration": {
      "customSipHeader": "exampleHeaderContents"
    }
  },
  "etag": "\"19004107-0000-0700-0000-65084ad60000\""
}

Update configuration for a number

Use PUT on the account/<accountName>/numbers/<phoneNumber> endpoint to update configuration for a number. To ensure that the update doesn't overwrite a change made by another user, add an If-Match header with the ETag from the most recent response for the number.

Request:

PUT /account/contoso/numbers/%2B123451?api-version=2023-10-01 HTTP/1.1

If-Match: "19004107-0000-0700-0000-65084ad60000"
Content-Type: application/json

{
  "services": {
    "teamsDrEnabled": true,
    "teamsOcEnabled": false,
    "zoomEnabled": false
  },
  "configuration": {
    "customSipHeader": "exampleNewHeader"
  }
}

Response:

HTTP/1.1 200 OK

{
  "phoneNumber": "+123451",
  "accountName": "contoso",
  "details": {
    "services": {
      "teamsDrEnabled": true,
      "teamsOcEnabled": false,
      "zoomEnabled": false
    },
    "configuration": {
      "customSipHeader": "exampleNewHeader"
    }
  },
  "etag": "\"19007a0a-0000-0700-0000-65084ca00000\""
}

Add or update multiple numbers at once

Use POST on the account/<accountName>/numbers:batch endpoint to add up to 100 numbers to the account at once. This endpoint can also be used to update numbers in the account. The numbers are added transactionally: if any update fails, all updates fail.

Request:

POST /account/contoso/numbers:batch?api-version=2023-10-01 HTTP/1.1

Content-Type: application/json

{
  "numbers": [
    {
      "phoneNumber": "+123452",
      "details": {
        "services": {
          "teamsDrEnabled": true,
          "teamsOcEnabled": false,
          "zoomEnabled": false
        },
        "configuration": {
          "customSipHeader": "exampleHeaderContents"
        }
      }
    },
    {
      "phoneNumber": "+123453",
      "details": {
        "services": {
          "teamsDrEnabled": true,
          "teamsOcEnabled": false,
          "zoomEnabled": false
        },
        "configuration": {
          "customSipHeader": "exampleHeaderContents"
        }
      }
    }
  ]
}

Response:

HTTP/1.1 200 OK

{
  "numbers": [
    {
      "phoneNumber": "+123452",
      "accountName": "contoso",
      "details": {
        "services": {
          "teamsDrEnabled": true,
          "teamsOcEnabled": false,
          "zoomEnabled": false
        },
        "configuration": {
          "customSipHeader": "exampleHeaderContents"
        }
      },
      "etag": "\"19002b0c-0000-0700-0000-65084d900000\""
    },
    {
      "phoneNumber": "+123453",
      "accountName": "contoso",
      "details": {
        "services": {
          "teamsDrEnabled": true,
          "teamsOcEnabled": false,
          "zoomEnabled": false
        },
        "configuration": {
          "customSipHeader": "exampleHeaderContents"
        }
      },
      "etag": "\"19002c0c-0000-0700-0000-65084d900000\""
    }
  ]
}

Get all numbers in the account

Use GET on the account/<accountName>/numbers endpoint to get all numbers in the account with their configuration. Use the skip and maxpagesize query parameters to control how the response is paginated. If there are more numbers to be returned, the response will contain a nextLink field indicating the URL to request to get the next page of results.

Request:

GET /account/contoso/numbers?api-version=2023-10-01&skip=0&maxpagesize=2 HTTP/1.1

Response:

HTTP/1.1 200 OK

{
  "value": [
    {
      "phoneNumber": "+123451",
      "accountName": "contoso",
      "details": {
        "services": {
          "teamsDrEnabled": true,
          "teamsOcEnabled": false,
          "zoomEnabled": false
        },
        "configuration": {
          "customSipHeader": "exampleNewHeader"
        }
      },
      "etag": "\"19007a0a-0000-0700-0000-65084ca00000\""
    },
    {
      "phoneNumber": "+123452",
      "accountName": "contoso",
      "details": {
        "services": {
          "teamsDrEnabled": true,
          "teamsOcEnabled": false,
          "zoomEnabled": false
        },
        "configuration": {
          "customSipHeader": "exampleHeaderContents"
        }
      },
      "etag": "\"19002b0c-0000-0700-0000-65084d900000\""
    }
  ],
  "nextLink": "https://<api-fqdn>/account/contoso/numbers?api-version=2023-10-01&skip=2&maxpagesize=2"
}

Troubleshooting

  • Teams Direct Routing isn't working for numbers on an account.

    • Check the DNS token has been validated by sending a GET on the account with the ?status=true query parameter, and verify the directRoutingProvisioningState has subdomainStatus equal to Provisioned.
  • I configured a number to use Direct Routing/Zoom, but it doesn't seem to be working.

    • Check that the account is configured to use Direct Routing/Zoom, and that the number has this specific feature enabled.
  • I can contact the API, but after making multiple requests my connections start timing out.

Next steps

Start integrating with the Azure Communications Gateway Provisioning API.