The XMAP Hub API can authenticate calls from your own systems (a CRM, a Power Platform flow, a back-office integration) using OAuth 2.0 with tokens issued by your council's own Microsoft Entra ID tenant. You keep full control of the credentials: you create them, you rotate them, and you can switch them off at any time without contacting Geoxphere.
This article explains how the two sides fit together and walks through the setup. It is written for an Entra administrator working with the person who owns the integration.
Every OAuth call involves two applications:
When an administrator in your tenant grants your client application permission to use XMAP API, Entra automatically creates an entry for XMAP API under Enterprise applications in your tenant. That entry is what links the two tenants. It is also your off switch: disabling it blocks every token for the Hub API from your tenant.
Your system then asks your tenant for a token, using the client credentials grant (no user signs in). The token names XMAP API as its audience and lists the permissions your administrator granted. The Hub API checks that the token came from a tenant Geoxphere has recorded for your council, that it is signed by your tenant, and that it carries the permission the endpoint needs.
Note: The permissions are application permissions (sometimes shown as app roles), not delegated permissions. Application permissions are the only kind that can appear in a token requested without a signed-in user.
| Permission | What it allows |
|---|---|
Hub.Custom | Call your council's custom lookup endpoints (for example, "what is at this point" or "find the nearest asset"). |
Hub.Report | Submit reports (Report It) on behalf of your system, for example from a CRM case. |
Request only the permissions your integration needs. Each endpoint checks for its own permission.
Because XMAP API belongs to another organisation, it has to be linked into your tenant once before it appears in any permission list. Choose either method:
https://login.microsoftonline.com/<your tenant ID>/adminconsent?client_id=<XMAP API application ID>&redirect_uri=https://oauth.hub.xmap.cloud/oauth/consented.html. After you accept, a confirmation page on oauth.hub.xmap.cloud shows your tenant ID with a copy button, ready for step 5.# Azure CLI
az ad sp create --id <XMAP API application ID>
# Microsoft Graph PowerShell
New-MgServicePrincipal -AppId "<XMAP API application ID>"Afterwards, Enterprise applications in your tenant lists an application called XMAP API.
Warning: Set a calendar reminder before the secret expires. An expired secret stops the integration with an authentication error on the token request.
Hub.Custom and/or Hub.Report, then click Add permissions.Note: If XMAP API does not appear in the list, step 1 has not been completed in your tenant. Permissions only take effect after admin consent is granted; without it, tokens are issued but contain no permissions and the Hub API returns 403.
Email your Geoxphere contact or raise a support ticket with:
Never send the client secret. Geoxphere does not need it and will not ask for it.
Geoxphere records your tenant and client against your council's account. Until that is done, valid tokens from your tenant are refused with 403 Not authorised.
Your system requests a token from your tenant, then sends it as a bearer token to the Hub API. Replace the placeholders with your values.
POST https://login.microsoftonline.com/<your tenant ID>/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&client_id=<your client application ID>
&client_secret=<your client secret>
&scope=api://<XMAP API application ID>/.defaultThe response contains access_token and expires_in (typically 3,600 to 5,400 seconds). Then:
GET https://<hub api host>/<council id>/custom/<endpoint id>?x=403163.94&y=301844.54
Authorization: Bearer <access_token>A complete example with curl:
TOKEN=$(curl -s -X POST "https://login.microsoftonline.com/$TENANT_ID/oauth2/v2.0/token" \
--data-urlencode grant_type=client_credentials \
--data-urlencode client_id="$CLIENT_ID" \
--data-urlencode client_secret="$CLIENT_SECRET" \
--data-urlencode scope="api://$XMAP_API_APP_ID/.default" | jq -r .access_token)
curl -H "Authorization: Bearer $TOKEN" \
"https://$HUB_API_HOST/$COUNCIL_ID/custom/$ENDPOINT_ID?x=403163.94&y=301844.54"Note: The value /.default at the end of the scope is required for the client credentials grant. It means "all the application permissions this client has been granted for XMAP API". Do not replace it with a permission name.
expires_in. Do not request a new token for every API call.Retry-After header. The Hub API applies a per-address rate limit.Retry-After value. It means the Hub API could not reach Entra to check the token's signature.You can stop your integration calling the Hub API at any time, without involving Geoxphere:
Tokens already issued remain valid until they expire (at most about 90 minutes). If you need access stopped immediately, also ask Geoxphere to remove your tenant from your council's configuration, which takes effect on the next request.
| Symptom | Likely cause and fix |
|---|---|
Token request fails with AADSTS500011 (resource principal not found) | XMAP API has not been linked into your tenant. Complete step 1. |
Token request fails with AADSTS700016 (application not found in the directory) | The client_id is not your client application's Application (client) ID. The usual slip is pasting the Object ID from the Overview page, or the Secret ID shown next to the secret value. Copy the Application (client) ID from the Overview page. If it is correct, check the tenant ID in the token URL is the tenant the application was registered in. |
Token request fails with AADSTS1002012 (scope not valid) | A permission name such as Hub.Custom was used as the scope. For the client credentials grant the scope must be api://<XMAP API application ID>/.default. The permissions come back inside the token, not from the scope. |
Token request fails with AADSTS7000215 or AADSTS7000222 | The client secret is wrong or has expired. Create a new secret (step 3). |
Token request fails with AADSTS7000216 | The secret was not sent. Check your request body includes client_secret (and that shell variables are set if scripting). |
Hub API returns 401 with Authentication required | No Authorization: Bearer header reached the API. Check the header name and that it is not being stripped by a proxy. |
Hub API returns 401 with Invalid token | The token has expired, was requested for the wrong scope, or was altered in transit. Request a new token with the exact scope shown in step 6. |
Hub API returns 403 with Not authorised | Either admin consent has not been granted (the token has no permissions), the permission for that endpoint was not granted, or Geoxphere has not yet recorded your tenant and client. Check step 4, then step 5. Remember to request a fresh token after granting consent. |
| XMAP API does not appear under APIs my organization uses | Step 1 has not been completed, or the portal list is cached. Refresh the page or search by application ID. |