{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":[]},"type":"markdown"},"seo":{"title":"Authentication","description":"Hyperproof developer resources for custom integrations.","llmstxt":{"hide":false,"sections":[{"title":"Table of contents","includeFiles":["**/*"],"excludeFiles":[]}],"excludeFiles":[]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"authentication","__idx":0},"children":["Authentication"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The Hyperproof TPRM Core API uses ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["OAuth 2.1 ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["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."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"1-get-your-api-credentials","__idx":1},"children":["1. Get your API credentials"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Before you can call the API, you need a ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["client_id"]}," and a ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["client_secret"]},"."," ","They are issued per organization from the ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Hyperproof app"]},": an organization admin"," ","opens the API credentials screen and creates a client."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Each organization has ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["one client_id"]},", which can hold ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["multiple secrets"]},","," ","each with its own set of scopes. This lets you:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["issue a separate secret for each integration, and revoke just that one;"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["rotate without downtime"]}," — create a new secret, migrate your integration"," ","to it, then retire the old one. Both secrets work during the overlap."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The plaintext secret is shown ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["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."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["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."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"2-exchange-credentials-for-a-token","__idx":2},"children":["2. Exchange credentials for a token"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Send ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["grant_type=client_credentials"]}," in the form body, and authenticate with"," ","HTTP Basic (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client_id:client_secret"]},"):"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"bash","header":{"controls":{"copy":{}}},"source":"curl -X POST https://api.expent.ai/tprm-api/oauth/token \\\n  -u \"CLIENT_ID:CLIENT_SECRET\" \\\n  --data-urlencode grant_type=client_credentials\n# -> {\"access_token\":\"eyJ…\",\"token_type\":\"Bearer\",\"expires_in\":600,\"scope\":\"…\"}\n","lang":"bash"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Access tokens are ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["self-contained JWTs"]}," and are valid for ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["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."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"3-call-the-api","__idx":3},"children":["3. Call the API"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Send the token as a Bearer token:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"bash","header":{"controls":{"copy":{}}},"source":"curl -X POST https://api.expent.ai/tprm-api/vendors/search \\\n  -H \"Authorization: Bearer ACCESS_TOKEN\" \\\n  -H \"Content-Type: application/json\" -d '{}'\n","lang":"bash"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"scopes--ask-only-for-what-you-need","__idx":4},"children":["Scopes — ask only for what you need"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Your client is granted a fixed set of scopes. Omit the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["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"," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["400 invalid_scope"]},"."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"bash","header":{"controls":{"copy":{}}},"source":"curl -X POST https://api.expent.ai/tprm-api/oauth/token \\\n  -u \"CLIENT_ID:CLIENT_SECRET\" \\\n  --data-urlencode grant_type=client_credentials \\\n  --data-urlencode 'scope=tprm.vendors.read tprm.vendors.write'\n","lang":"bash"},"children":[]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Scope"},"children":["Scope"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Grants"},"children":["Grants"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tprm.vendors.read"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["List, search, and read vendors and vendor fields."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tprm.vendors.write"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Create, update, archive, and delete vendors."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tprm.assessments.read"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["List and read assessments and their responses."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tprm.documents.read"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["List a vendor's documents and download their files."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tprm.monitoring.read"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Read vendor risk-monitoring status and results."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tprm.exports.read"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Request assessment, risk-register, and risk-monitor exports; poll and download them."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tprm.users.read"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Export your organization's users. The user directory is PII, so it has its own scope."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tprm.stats.read"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Read your organization's daily TPRM statistics snapshots."]}]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"need-stronger-token-security","__idx":5},"children":["Need stronger token security?"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For integrations that require it, tokens can be ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["sender-constrained with"," ","DPoP"]},", which makes a stolen token useless without the matching private key."," ","See the ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["DPoP"]}," guide."]}]},"headings":[{"value":"Authentication","id":"authentication","depth":1},{"value":"1. Get your API credentials","id":"1-get-your-api-credentials","depth":2},{"value":"2. Exchange credentials for a token","id":"2-exchange-credentials-for-a-token","depth":2},{"value":"3. Call the API","id":"3-call-the-api","depth":2},{"value":"Scopes — ask only for what you need","id":"scopes--ask-only-for-what-you-need","depth":2},{"value":"Need stronger token security?","id":"need-stronger-token-security","depth":2}],"frontmatter":{"seo":{"title":"Authentication"}},"lastModified":"2026-08-11T17:44:00.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/hyperproof-tprm/authentication","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}