Skip to main content

Documentation Index

Fetch the complete documentation index at: https://vanta.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

You’ll create a UserAccount record visible on the Access page, your app listed under Settings → Integrations, and Vanta’s standard compliance tests for user accounts running against the data you pushed.

Before you begin

Make sure you have:
  • Vanta partner account.
  • A web app with a server-side component that can complete an OAuth authorization-code flow.
  • A publicly reachable HTTPS redirect URI (HTTP is allowed only for localhost and 127.0.0.1 during development).
Building a private integration to connect a homegrown app, on-prem system, or unsupported SaaS tool to your own Vanta tenant? Private integrations are single-tenant and use the simpler client_credentials grant — skip the OAuth steps and follow the Build a Private Integration quickstart instead.
1

Create a Build Integrations application

Vanta Dashboard — sign in to Vanta app with the partner email Vanta provided ([your_email]+connectors@[your_company].com). Vanta sends a magic link; check spam if you don’t see it.Open Settings → Developer Console and click Create. Choose Build Integrations as the app type, then select Public for the distribution. Fill in:
  • Application name — what customers see in the Vanta marketplace.
  • Application description — a brief description of your integration.
  • Application category — determines marketplace placement.
  • Uploads documents — check this if your integration uploads file-based evidence.
  • Application URL — the URL where users access your tool (e.g. app.yourtool.com, not the marketing page).
  • Installation URL — where the marketplace sends customers to start the OAuth flow. Not the same as your redirect_uri. Vanta Developer Console showing the Build Integrations app creation form with Public distribution selected
The OAuth client_id is auto-generated. Click Generate client secret to create the secret. Store both values securely on your server. You can rotate the secret at any time without invalidating active customer tokens.
2

Register a redirect URI

Vanta Dashboard — in the Developer Console, register one or more redirect URIs for your application. When a user authorizes your integration, Vanta sends them back to one of these URIs with an authorization code.
URI format requirements
  • Must be HTTPS, except for localhost and 127.0.0.1 (HTTP allowed for development).
  • Custom ports are allowed for localhost/127.0.0.1.
  • May contain query parameters but must not contain URL fragments (#).
Examples: https://example.com/oauth/callback/vanta, http://localhost:8000/oauth/callback/vanta, http://127.0.0.1/callback?some-param=value.
3

Initiate the OAuth flow

From your server, redirect the user’s browser to https://app.vanta.com/oauth/authorize. A complete authorization URL looks like:
https://app.vanta.com/oauth/authorize?client_id=vci_your_client_id&scope=connectors.self:write-resource%20connectors.self:read-resource&state=xyzABC123&redirect_uri=https://partner-app.com/oauth/callback&source_id=acct1234&response_type=code
Query parameters:
ParameterDescription
client_idFrom the Developer Console.
scopeSpace-separated list of scopes (see below).
stateAn opaque random string you generate, store in the user’s session, and compare on callback. Confirms the response came from the flow you started (CSRF protection).
redirect_uriMust match a redirect URI registered in Step 2.
source_idUnique identifier for the user’s account in your application (e.g. accountId). Allows multiple of your accounts to connect to the same Vanta account. Make this human-readable.
response_typeAlways code.
This quickstart requests two scopes:
  • connectors.self:write-resource — send resources to Vanta on behalf of users.
  • connectors.self:read-resource — read resources you previously sent (used in Step 7 to verify).
The user sees a Vanta authorization screen, clicks Allow, and Vanta redirects them to your redirect_uri with code and state query parameters appended. The integration also appears in the customer’s tenant under Settings → Integrations with the application name you set in Step 1.
Verify state on callback. Compare the returned state against the value you stored in the user’s session before exchanging the code. If they don’t match, abort the flow.
If Vanta redirects with an error query param, the code identifies the failure:
CodeCause
1The initial redirect to Vanta is missing required query parameters.
2Invalid scopes.
3Invalid responseType (must be code).
4Error loading the registered application.
5Application not found — check client_id.
6redirect_uri is not registered in the Developer Console.
4

Exchange the code for an access token

On your server, exchange the authorization code for an access token within 30 seconds of receiving it — after that the code expires and the user must reauthorize.
curl --location 'https://api.vanta.com/oauth/token' \
  --header 'Content-Type: application/json' \
  --data '{
    "client_id": "vci_your_client_id",
    "client_secret": "vcs_your_client_secret",
    "code": "vac_authorization_code_from_callback",
    "source_id": "acct1234",
    "redirect_uri": "https://partner-app.com/oauth/callback",
    "grant_type": "authorization_code"
  }'
Expected response:
{
  "access_token": "your_access_token",
  "refresh_token": "your_refresh_token",
  "expires_in": 3600,
  "token_type": "Bearer"
}
Both access_token and refresh_token are sensitive — store them securely, scoped per user. When the access token expires (1 hour), exchange the refresh_token for a new pair via the same endpoint with grant_type: "refresh_token". The previous refresh token expires 3 hours after first use to refresh — make sure you persist the new one.
Configure automatic retries on 5xx errors and network failures, or your user may need to re-authorize.
Double-check the client_id and client_secret from the Developer Console. If you rotated the secret, the old one is no longer valid. Make sure your Content-Type header is application/json — Vanta’s /oauth/token does not accept form-encoded bodies. Most off-the-shelf OAuth libraries default to application/x-www-form-urlencoded, so you may need to override that.
Authorization codes expire after 30 seconds. If you took longer than that to exchange the code, restart the flow from Step 3. The redirect_uri you send here must also exactly match the one you used to request the code.
5

Push your first resource

Most public integrations start with UserAccount — Vanta’s representation of a user record in your system, used for access reviews and management. PUT is idempotent on uniqueId, so it’s safe to retry on network errors.From your server, replace your_token_here with the customer’s access_token from Step 4 and push a record:
curl --request PUT 'https://api.vanta.com/v1/resources/user_account' \
  --header 'Authorization: Bearer your_token_here' \
  --header 'Content-Type: application/json' \
  --data '{
    "resources": [
      {
        "uniqueId": "user_123",
        "displayName": "Jane Doe",
        "fullName": "Jane Doe",
        "accountName": "jane.doe",
        "email": "[email protected]",
        "status": "ACTIVE",
        "mfaEnabled": true,
        "mfaMethods": ["SMS", "EMAIL"],
        "authMethod": "SSO",
        "permissionLevel": "ADMIN",
        "externalUrl": "https://app.example.com/users/user_123",
        "createdTimestamp": "2026-05-05T00:00:00Z",
        "updatedTimestamp": "2026-05-05T00:00:00Z"
      }
    ]
  }'
Expected response (200 OK):
{
  "results": {
    "accepted": 1,
    "rejected": 0
  }
}
Each PUT represents the full state of resources you own for that customer. Any uniqueId you previously pushed but omit from a later PUT is marked as no longer existing in Vanta. Sync the complete set on every run.
Tests are generated for you. As soon as you push a base resource type (e.g. UserAccount, Computer, Vulnerability), Vanta automatically creates and runs the standard out-of-the-box tests for that resource in the customer’s tenant — there’s nothing to wire up. Authoring Custom Tests is not currently supported for public integrations.
Push resources on a periodic schedule (typically hourly) for each customer’s tenant to stay current. See per-type schemas in the Build Integrations API reference.
Your access token has expired (tokens last one hour) or your app wasn’t granted the connectors.self:write-resource scope. Refresh per Step 4 and retry — if that still fails, re-run the OAuth flow from Step 3 with the correct scopes.
6

Disconnect when a user uninstalls

When a user disconnects your integration in your app, your server must call the Suspend API so Vanta cleans up its side and revokes the user’s tokens.
curl --request POST 'https://api.vanta.com/v1/oauth/token/suspend' \
  --header 'Content-Type: application/json' \
  --data '{
    "token": "your_access_or_refresh_token",
    "client_id": "your_client_id",
    "client_secret": "your_client_secret"
  }'
Expected response (200 OK — idempotent; same response if the token is already revoked):
{}
The token doesn’t belong to this client_id. Confirm you’re sending the credentials for the same application that minted the token, not a different app in your Developer Console.
{
  "message": "Token does not belong to this application",
  "statusCode": 401
}
7

Verify it worked

From your terminal, read back the resource you pushed in Step 5 to confirm the full flow — auth, write, and read — is wired correctly.
Terminal
curl 'https://api.vanta.com/v1/resources/user_account?pageSize=10' \
  --header 'Authorization: Bearer your_token_here' \
  --header 'Accept: application/json'
Then open the customer’s Vanta app and navigate to the Access page — the user you PUT should appear with the same displayName and email, and your integration should be listed under Settings → Integrations.
ScenarioTest inputExpected result
SuccessValid access_token after the PUT in Step 5200 OK, response data includes user_123; the user appears in the customer’s Vanta dashboard
Auth failureExpired or revoked access_token401 Unauthorized — refresh per Step 4 and retry
Edge caseRefresh-token rotation: exchange refresh_token for a new pair, then repeat the GET with the new access_token200 OK, same data — confirms rotation works without re-authorization
Edge caseA uniqueId you previously pushed but omitted from the latest PUTThe resource is marked as no longer existing in Vanta and disappears from GET results — confirms the full-state replacement model from Step 5

Congratulations

You have a working public integration — OAuth-authorized by a customer, pushing resources into their Vanta tenant, and verifiable via a read-back. From here you can:
  • Schedule it. Run the sync hourly per customer from cron, a queue worker, or your CI runner. Always refresh the access token at the start of each run.
  • Expand resource coverage. Push additional supported types (Computer, Vulnerability, BackgroundCheck, TrainingRecord, etc.) from the same app.
  • Harden refresh with automatic retries on 5xx so users don’t have to re-authorize after transient failures.
  • List your integration in the Vanta marketplace once you’re ready for customers to discover and install it.

Next steps

List your integration

Submit your integration for review and publish to the Vanta marketplace.

Supported resource types

Full reference of every resource type Vanta accepts out of the box.

Resources

Deep dive on the resource lifecycle, including custom resources.

Build Integrations API reference

Every endpoint available to Build Integrations apps.