Skip to main content

Authentication

Overview

The Voice ReGen Service API uses Microsoft Entra ID for authentication. To authenticate, the API client sends the following parameters to Microsoft Entra ID and receives an access token in response.

ParameterDescription
Tenant IDIdentifies the Microsoft Entra ID tenant used for authentication. You can find this value in the API Keys tab.
Client IDThe client identifier for the API key/application credentials. You can find this value in the API key you created.
Client SecretThe API key secret shown when the API key was created.
ScopeThe fixed default scope for Voice ReGen API access. You can find this value in the API Keys tab.

The API client application must include the access token received from Microsoft Entra ID in every API call:

-H "Authorization: Bearer <access_token>"

Access Token Expiration and Renewal

The access_token is valid for 1 hour. We recommend implementing a token renewal mechanism.

Authentication - Getting the Access Token

Request a token from the Microsoft Entra ID authentication endpoint:

https://login.microsoftonline.com/<tenantId>/oauth2/v2.0/token
TENANT_ID="<tenantId>"
CLIENT_ID="<clientId>"
CLIENT_SECRET="<clientSecret>"
SCOPE="api://<application-id-uri>/.default"

curl -s -X POST "https://login.microsoftonline.com/$TENANT_ID/oauth2/v2.0/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "client_id=$CLIENT_ID" \
--data-urlencode "client_secret=$CLIENT_SECRET" \
--data-urlencode "grant_type=client_credentials" \
--data-urlencode "scope=$SCOPE"

Microsoft Entra ID token response example:

{
"access_token": "...",
"token_type": "Bearer",
"expires_in": 3599,
"ext_expires_in": 3599
}

Using the Token with Service API Endpoints

Once you have an access_token, call the Voice ReGen endpoint:

API_BASE_URL="<api-base-url>"
ACCESS_TOKEN="<access_token>"

curl -s -X POST "$API_BASE_URL/api/v1/getFilesStatus" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{ "fileIds": ["file-123"] }'

Token Renewal Example (Node.js + TypeScript)

With client_credentials, Microsoft Entra ID does not issue a refresh token. The API client application needs to:

  • Cache the access token used with each request.
  • Fetch a new token before the current one expires.

Below is a sample implementation for token renewal:

Token manager (cache + auto-renewal)
type TokenResponse = {
access_token: string;
token_type: 'Bearer';
expires_in: number; // seconds
};

export class EntraAccessTokenProvider {
private token: string | null = null;
private expiresAtMs = 0;
private refreshInFlight: Promise<string> | null = null;

constructor(
private readonly opts: {
tenantId: string;
clientId: string;
clientSecret: string;
scope: string; // e.g. api://<application-id-uri>/.default
// refresh slightly early to avoid edge cases / clock skew
refreshSkewMs?: number;
},
) {}

async getAccessToken(): Promise<string> {
const skew = this.opts.refreshSkewMs ?? 60_000;
const now = Date.now();

if (this.token && now + skew < this.expiresAtMs) {
return this.token;
}

if (!this.refreshInFlight) {
this.refreshInFlight = this.fetchNewToken().finally(() => {
this.refreshInFlight = null;
});
}

return this.refreshInFlight;
}

private async fetchNewToken(): Promise<string> {
const tokenUrl = `https://login.microsoftonline.com/${this.opts.tenantId}/oauth2/v2.0/token`;
const body = new URLSearchParams({
client_id: this.opts.clientId,
client_secret: this.opts.clientSecret,
grant_type: 'client_credentials',
scope: this.opts.scope,
});

const res = await fetch(tokenUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body,
});

if (!res.ok) {
throw new Error(
`Token request failed: ${res.status} ${res.statusText} - ${await res.text()}`,
);
}

const json = (await res.json()) as TokenResponse;
this.token = json.access_token;
this.expiresAtMs = Date.now() + json.expires_in * 1000;
return this.token;
}
}

// Usage
const voiceRegenConfig = {
tenantId: '<tenantId>',
clientId: '<clientId>',
clientSecret: '<clientSecret>',
scope: 'api://<application-id-uri>/.default',
apiBaseUrl: '<api-base-url>',
};

const tokenProvider = new EntraAccessTokenProvider({
tenantId: voiceRegenConfig.tenantId,
clientId: voiceRegenConfig.clientId,
clientSecret: voiceRegenConfig.clientSecret,
scope: voiceRegenConfig.scope,
});

async function callVoiceRegen() {
const accessToken = await tokenProvider.getAccessToken();

const resp = await fetch(
`${voiceRegenConfig.apiBaseUrl}/api/v1/getFilesStatus`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${accessToken}`,
},
body: JSON.stringify({ fileIds: ['file-123'] }),
},
);

return resp.json();
}