API Access: Host, Authentication, Credentials
The one fact that matters
DTC's HaloPSA instance is https://psa.dtctoday.com. Every API call, token request and portal integration uses that host.
| What | URL |
|---|---|
| Agent app | https://psa.dtctoday.com |
| REST API base | https://psa.dtctoday.com/api |
| OAuth token endpoint | https://psa.dtctoday.com/auth/token |
| OpenID discovery | https://psa.dtctoday.com/auth/.well-known/openid-configuration |
dtc.halopsa.com is not our instance. It resolves and serves a Halo login page, and its /auth/token answers every request with Halo's generic "Sorry, something went wrong" page, which looks like an outage rather than a wrong host. Corey's soft-audit register already lists the two hosts as a contradiction (OPS-17); the client-portal .env examples carried the wrong one until 2026-10-19.
Authentication (client credentials)
POST https://psa.dtctoday.com/auth/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&client_id=<id>&client_secret=<secret>&scope=all
Response: access_token (bearer, 3600 s), token_type, expires_in, scope. A tenant parameter is accepted but not needed on this instance.
Quick check that the host and credentials are right:
curl -s https://psa.dtctoday.com/auth/token \
--data-urlencode grant_type=client_credentials \
--data-urlencode client_id="$HALO_CLIENT_ID" \
--data-urlencode client_secret="$HALO_CLIENT_SECRET" \
--data-urlencode scope=all | head -c 80
A JSON body starting {"access_token": means both are right. An HTML page means the host is wrong; invalid_client means the credential is.
API applications and credentials
API applications live in Halo under Configuration > Integrations > HaloPSA API. Client-credentials applications must log in as an Integrator Agent (SSO accounts do not work with the client-credentials flow; see the GUID Sync page).
All secrets are in 1Password, team account team-dtc.1password.com. Never in a repo, a .env committed to git, a KB page or a chat.
| Application | 1Password item | Used by |
|---|---|---|
| Client portal service | PROD HaloPSA DTC Client Portal Service | client-portal api (prod) and workstation sessions acting for the portal |
| n8n | PROD N8N HaloPSA API Credentials | n8n workflows |
| FSDM | FSDM HaloPSA API Key | Financial Data Sync Manager |
| NinjaRMM GUID sync | Halo/NinjaRMM API - GUID Sync Secret | the weekly GUID sync script |
| Dev script key | HaloPSA API Key - Dev - API Script Run | one-off bulk updates |
Client id is the item's username; the secret is credential (or password on the dev key).
Where the host is configured
| System | Setting |
|---|---|
| client-portal on AKS | HALO_BASE_URL and HALO_AUTH_BASE_URL in dtc-infra/apps/client-portal/base/deployment-api.yaml |
client-portal .env examples |
.env.dev.example, .env.prod.example (corrected 2026-10-19) |
| Apis (AI) profile | its CLAUDE.md, Scope section |
| StackJack MCP connector | configured on the StackJack side; a 403 from the connector says nothing about the API itself |