Skip to main content

Authentication with OAuth 2.0

Every AgencyMax API operation needs an OAuth 2.0 bearer access token (a JWT) in the Authorization header, along with your subscription key.

Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...

Identity provider​

The APIs trust tokens issued by the AgencyMax identity provider (the authority). Most agencies use the shared AgencyMax authority. An agency can also be set up with its own authority. Either way, the authority publishes its token endpoint and signing keys in its OpenID Connect discovery document:

{authority}/.well-known/openid-configuration

Your AgencyMax representative will give you the authority URL, a client ID and a client secret for each environment.

Getting a token (client credentials)​

For server-to-server integrations, use the OAuth 2.0 client credentials grant. Request the scopes you need, separated by spaces. The list must always include your tenant scope.

curl -X POST "$TOKEN_ENDPOINT" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=$CLIENT_ID" \
-d "client_secret=$CLIENT_SECRET" \
--data-urlencode "scope=tenant:acme read:agents write:agents"
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "tenant:acme read:agents write:agents"
}

Example in C#​

using var http = new HttpClient();

var tokenResponse = await http.PostAsync(tokenEndpoint, new FormUrlEncodedContent(new Dictionary<string, string> {
["grant_type"] = "client_credentials",
["client_id"] = clientId,
["client_secret"] = clientSecret,
["scope"] = "tenant:acme read:agents"
}));
tokenResponse.EnsureSuccessStatusCode();
var token = await tokenResponse.Content.ReadFromJsonAsync<JsonElement>();
var accessToken = token.GetProperty("access_token").GetString();

var request = new HttpRequestMessage(HttpMethod.Get, "https://api.agencymax.example.com/agency-management/acme/agents/A1001");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
request.Headers.Add("Ocp-Apim-Subscription-Key", subscriptionKey);
var response = await http.SendAsync(request);

Scopes​

Two kinds of scope control access.

Tenant scope​

Tenant-scoped operations need the scope tenant:<tenantIdentifier>, and it must match the tenant identifier in the request URL. A token for tenant acme can call /acme/... but gets 403 Forbidden on /globex/.... See Tenants.

API scopes​

Each operation also needs an API-specific scope:

APIScopeGrants
Agency Managementread:agentsRead agents and all related data: certifications, payees, teams, reference data and so on.
write:agentsCreate and update agents and related data.
delete:agentsPermanently delete agents.
Agent Onboardingagent-onboarding:app-configuration:readRead onboarding app configuration, contracts, covenants and background questions.
agent-onboarding:applications:readRead agent applications.
agent-onboarding:applications:writeCreate, update and validate agent applications.
Business Insightsbusiness-insights:queries:executeRun business queries.
business-insights:report-recipes:readRead report recipes.
business-insights:report-recipes:writeCreate, update and delete report recipes.
Identity Managementread:usersRead users.
write:usersCreate and update users.
read:rolesRead roles.
Webhooksread:webhook-subscriptionsRead webhook subscriptions and delivery history.
write:webhook-subscriptionsCreate, update and delete webhook subscriptions.
caution

Upcoming scope renames

The Identity Management and Webhooks scopes are due to move to the newer <api>:<resource>:<action> naming, for example identity:users:read, identity:roles:read and webhooks:subscriptions:write. Any rename will be announced in the Release Notes with a transition period.

Request only the scopes your integration needs.

Token lifetime and caching​

  • Tokens expire; expires_in gives the lifetime in seconds. Cache each token and reuse it until shortly before it expires, for example 60 seconds early. Don't request a new token for every API call. The identity provider throttles token requests.
  • If an API call returns 401 Unauthorized with a WWW-Authenticate: Bearer ... header, the token has probably expired. Get a new token and retry once.

Authentication and authorization errors​

StatusMeaningWhat to do
401 UnauthorizedThe token is missing, malformed or expired, has an invalid signature, or came from an untrusted authority.Check the Authorization header and get a fresh token.
403 ForbiddenThe token is valid but lacks the tenant scope for the URL's tenant, or lacks the operation's API scope.Request a token with the right scopes. Contact AgencyMax if your client isn't allowed to request them.
tip

A 401 or 403 can also come from the API gateway if the subscription key is the problem. See Subscription keys.