The Hyperproof TPRM Core API uses OAuth 2.1 client_credentials. You exchange a client id and a client secret for a short-lived access token, and then send that token as a Bearer token on every request.
Before you can call the API, you need a client_id and a client_secret. They are issued per organization from the Hyperproof app: an organization admin opens the API credentials screen and creates a client.
Each organization has one client_id, which can hold multiple secrets, each with its own set of scopes. This lets you:
- issue a separate secret for each integration, and revoke just that one;
- rotate without downtime — create a new secret, migrate your integration to it, then retire the old one. Both secrets work during the overlap.
The plaintext secret is shown only once, at creation (or through a one-time reveal link). Store it somewhere safe. Hyperproof keeps only an encrypted copy and can never show it to you again; if you lose it, rotate the secret to get a new one.
Credentials are managed in the Hyperproof app under your organization login, not through this external API. There is deliberately no endpoint here that returns a plaintext secret.
Send grant_type=client_credentials in the form body, and authenticate with HTTP Basic (client_id:client_secret):
curl -X POST https://api.expent.ai/tprm-api/oauth/token \
-u "CLIENT_ID:CLIENT_SECRET" \
--data-urlencode grant_type=client_credentials
# -> {"access_token":"eyJ…","token_type":"Bearer","expires_in":600,"scope":"…"}Access tokens are self-contained JWTs and are valid for 10 minutes. Hyperproof keeps no server-side session, so there is no refresh token for this grant. When a token expires, simply request a new one.
Send the token as a Bearer token:
curl -X POST https://api.expent.ai/tprm-api/vendors/search \
-H "Authorization: Bearer ACCESS_TOKEN" \
-H "Content-Type: application/json" -d '{}'Your client is granted a fixed set of scopes. Omit the scope parameter on the token request to receive all of them, or pass a space-separated subset to limit the token. Requesting a scope your client was not granted returns 400 invalid_scope.
curl -X POST https://api.expent.ai/tprm-api/oauth/token \
-u "CLIENT_ID:CLIENT_SECRET" \
--data-urlencode grant_type=client_credentials \
--data-urlencode 'scope=tprm.vendors.read tprm.vendors.write'| Scope | Grants |
|---|---|
tprm.vendors.read | List, search, and read vendors and vendor fields. |
tprm.vendors.write | Create, update, archive, and delete vendors. |
tprm.assessments.read | List and read assessments and their responses. |
tprm.documents.read | List a vendor's documents and download their files. |
tprm.monitoring.read | Read vendor risk-monitoring status and results. |
tprm.exports.read | Request assessment, risk-register, and risk-monitor exports; poll and download them. |
tprm.users.read | Export your organization's users. The user directory is PII, so it has its own scope. |
tprm.stats.read | Read your organization's daily TPRM statistics snapshots. |
For integrations that require it, tokens can be sender-constrained with DPoP, which makes a stolen token useless without the matching private key. See the DPoP guide.