# List all API Endpoint Vulnerabilities Source: https://developer.vanta.com/api-reference/api-endpoint-vulnerabilities/list-all-api-endpoint-vulnerabilities /reference/build-integrations.json get /v1/resources/api_endpoint_vulnerability_connectors List `ApiEndpointVulnerabilityConnectors` resources for the given application. ** Headers ** ``` Authorization: Bearer ``` ** Scopes ** ``` connectors.self:read-resource ``` # Sync all API Endpoint Vulnerabilities Source: https://developer.vanta.com/api-reference/api-endpoint-vulnerabilities/sync-all-api-endpoint-vulnerabilities /reference/build-integrations.json put /v1/resources/api_endpoint_vulnerability_connectors To send us data related to API endpoint vulnerabilities. Note that you must first sync `VulnerableComponent` resources before sending us this data, and this sync should reference the `uniqueId` field in the `VulnerableComponent` resource. This call replaces ALL existing `ApiEndpointVulnerabilityConnectors` resources for the given app and `source_id` - this is a "state of the world" sync. In other words, if a `ApiEndpointVulnerabilityConnectors` resource is sent for a user in a previous `sync_all` call, but is not included in a later `sync_all` call for that customer, it is assumed to no longer exist and is deleted in Vanta. ** Headers ** ``` Authorization: Bearer ``` ** Scopes ** ``` connectors.self:write-resource ``` ** Schema ** Expand the `resources` array below for the schema of `ApiEndpointVulnerabilityConnectors`. # Create an auditor Source: https://developer.vanta.com/api-reference/auditors/create-an-auditor https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples post /auditors Create an auditor in Vanta. Rate limit: 10 requests / minute. # Accept evidence for an information request Source: https://developer.vanta.com/api-reference/audits/accept-evidence-for-an-information-request https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples post /audits/{auditId}/information-requests/{requestId}/accept-evidence Accepts evidence for an information request, confirming that all submitted evidence meets audit requirements. This action changes the request's approvalStatus to an approved state and creates an activity log entry. Acceptance workflow: 1. Auditor reviews submitted evidence 2. If evidence is satisfactory, auditor calls this endpoint 3. Request status changes to approved state and is considered complete for this audit cycle Use this endpoint when: - All required evidence has been submitted - Evidence quality meets audit standards - Evidence addresses all specified framework codes - No additional information is needed Rate limit: 50 requests / minute. # Create a comment for a control within an audit Source: https://developer.vanta.com/api-reference/audits/create-a-comment-for-a-control-within-an-audit https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples post /audits/{auditId}/controls/{controlId}/comments Creates a new comment on a control within an IRL audit. The comment author must be an auditor in the audit firm making the request. The comment will be associated with the control and visible to all authorized users. Returns 404 when the control is not part of the audit. Rate limit: 50 requests / minute. # Create a comment for an information request Source: https://developer.vanta.com/api-reference/audits/create-a-comment-for-an-information-request https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples post /audits/{auditId}/information-requests/{requestId}/comments Creates a new comment for an information request. The comment author must be an auditor in the audit firm making the request. The comment will be associated with the information request and visible to all authorized users. Rate limit: 50 requests / minute. # Create a comment for audit evidence Source: https://developer.vanta.com/api-reference/audits/create-a-comment-for-audit-evidence https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples post /audits/{auditId}/evidence/{auditEvidenceId}/comments Create a comment in Vanta for a piece of evidence. Rate limit: 25 requests / minute. # Create a custom control for an audit Source: https://developer.vanta.com/api-reference/audits/create-a-custom-control-for-an-audit https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples post /audits/{auditId}/controls/custom-controls Create a custom control for an audit. This endpoint supports classic audits only. Audits that use information request lists (IRL) are not supported and return a 422 error. Rate limit: 10 requests / minute. # Create a custom evidence request for an audit Source: https://developer.vanta.com/api-reference/audits/create-a-custom-evidence-request-for-an-audit https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples post /audits/{auditId}/evidence/custom-evidence-requests Create a custom evidence request for an audit. Rate limit: 10 requests / minute. # Create a new information request Source: https://developer.vanta.com/api-reference/audits/create-a-new-information-request https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples post /audits/{auditId}/information-requests Creates a new information request for an audit during audit setup or as requirements evolve. After creating all information requests, use POST /audits/{auditId}/share-information-request-list to make them visible to the customer organization. Until shared, requests remain in draft state visible only to auditors. New requests are created in an initial state indicating evidence is needed. The status progresses through the workflow: initial state → awaiting review → approved or flagged. Rate limit: 600 requests / minute. # Delete a comment for a control within an audit Source: https://developer.vanta.com/api-reference/audits/delete-a-comment-for-a-control-within-an-audit https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples delete /audits/{auditId}/controls/{controlId}/comments/{commentId} Deletes an existing comment on a control. Only the original author of the comment can delete it. The author is identified by their email address, which must match the email of the user who created the comment. Rate limit: 10 requests / minute. # Delete a comment for an information request Source: https://developer.vanta.com/api-reference/audits/delete-a-comment-for-an-information-request https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples delete /audits/{auditId}/information-requests/{requestId}/comments/{commentId} Deletes an existing comment for an information request. Only the original author of the comment can delete it. The author is identified by their email address, which must match the email of the user who created the comment. Rate limit: 25 requests / minute. # Delete an information request for an audit Source: https://developer.vanta.com/api-reference/audits/delete-an-information-request-for-an-audit https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples delete /audits/{auditId}/information-requests/{requestId} Deletes an information request for an audit. This performs a soft delete, marking the request as deleted (setting `deletionDate`) while preserving it in the system for audit history and compliance tracking. Soft deletion allows: - Maintaining complete audit trail of all requests ever created - Retrieving deleted requests via `changedSinceDate` for synchronization After deletion: - The request remains in list responses with `deletionDate` set, even when `changedSinceDate` is omitted Rate limit: 50 requests / minute. # Duplicate an IRL audit Source: https://developer.vanta.com/api-reference/audits/duplicate-an-irl-audit https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples post /audits/duplicate Duplicates an existing IRL audit into a new audit engagement with the supplied displayName, audit dates, early access date, and auditor roster. Company, audit type, and framework are copied from the source audit and cannot be changed. Each email in `allowAuditorEmails` must match an active user in the authenticated audit firm's domain. Provision auditors via `POST /auditors` before referencing them here, or copy emails from `GET /audits/{sourceAuditId}` → `allowAuditorEmails` when duplicating with the same roster. Information requests are copied from the source audit. After duplication: - Requests with Vanta evidence will be pre-filled and marked as internal review. Review them before sharing with your customer. - Requests where evidence was not available or was uploaded externally will need evidence added manually. - Evidence capture dates and due dates can be modified after duplication. Audits with generated information requests can be duplicated only after their information requests have been created successfully. Rate limit: 10 requests / minute. # Flag evidence for an information request Source: https://developer.vanta.com/api-reference/audits/flag-evidence-for-an-information-request https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples post /audits/{auditId}/information-requests/{requestId}/flag-evidence Flags evidence for an information request when it doesn't meet audit requirements, marking issues that need to be addressed before approval. This action changes the request's approvalStatus to a flagged state and creates an activity log entry. Flagging workflow: 1. Auditor reviews submitted evidence 2. If issues are found, auditor calls this endpoint with detailed reason 3. Request status changes to flagged state 4. Customer is notified and can see the reason in activity logs 5. Customer addresses issues and updates evidence 6. When ready, customer changes status back to awaiting review 7. Auditor reviews again and either flags again or accepts The `reason` field should clearly explain what's missing or incorrect so the customer knows exactly what to fix. This reason is visible to the customer and appears in the activity log. Rate limit: 50 requests / minute. # Get an audit evidence comment by ID Source: https://developer.vanta.com/api-reference/audits/get-an-audit-evidence-comment-by-id https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/evidence/{auditEvidenceId}/comments/{commentId} Retrieves a single comment on a classic audit evidence item by its ID. Soft-deleted comments (where `deletionDate !== null`) are included in the response. Clients should check `deletionDate` to determine whether the comment has been deleted. This matches `GET /audits/{auditId}/comments`, which supports `changedSinceDate` and returns soft-deleted comments for delta sync. Comments remain fetchable when the parent evidence item has been soft-deleted, so delayed webhook consumers can still resolve a comment ID after evidence deletion. Rate limit: 50 requests / minute. # Get an audit evidence item by ID Source: https://developer.vanta.com/api-reference/audits/get-an-audit-evidence-item-by-id https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/evidence/{auditEvidenceId} Retrieves a single classic audit evidence item by its ID, scoped to its audit. The response matches the entry `GET /audits/{auditId}/evidence` returns for the same item, so an evidence ID surfaced by a webhook can be resolved directly instead of paging the audit's full evidence list. Soft-deleted evidence (where `deletionDate !== null`) is included in the response. Clients should check `deletionDate` to determine whether the item has been deleted. This matches `GET /audits/{auditId}/evidence`, which supports `changedSinceDate` and returns soft-deleted evidence for delta sync. As on the list endpoint, `description` is null for deleted items. Rate limit: 250 requests / minute. # Get an information request by ID Source: https://developer.vanta.com/api-reference/audits/get-an-information-request-by-id https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/information-requests/{requestId} Retrieves a single information request by its ID for an audit, allowing external audit management systems to fetch the latest state of a specific request without paginating through the full list. This endpoint returns a 4xx HTTP error for a soft-deleted information request. To confirm deletion, use `GET /audits/{auditId}/information-requests`, which supports `changedSinceDate` and includes soft-deleted requests with `deletionDate` set. Rate limit: 50 requests / minute. # Get an information request comment by ID Source: https://developer.vanta.com/api-reference/audits/get-an-information-request-comment-by-id https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/information-requests/{requestId}/comments/{commentId} Retrieves a single comment on an information request by its ID. Soft-deleted comments (where `deletionDate !== null`) are included in the response. Clients should check `deletionDate` to determine whether the comment has been deleted. This matches `GET /audits/{auditId}/information-requests/{requestId}/comments`, which supports `changedSinceDate` and returns soft-deleted comments for delta sync. Comments are only resolvable while their information request exists. Once the request itself is deleted, this endpoint returns a 4xx HTTP error instead of the comment. Check the request's `deletionDate` using `GET /audits/{auditId}/information-requests` before treating its comments as deleted too. Rate limit: 50 requests / minute. # Get audit by ID Source: https://developer.vanta.com/api-reference/audits/get-audit-by-id https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId} Returns a single audit by ID, scoped to the audit firm. To identify IRL (Information Request List) audits, check for the presence of the `auditorRequestListMetadata` field. This field is only present for IRL-based audits and will be `undefined` for standard audits. The response includes `segments`, the audit's scope. It returns every in-scope program and system segment; more than one segment does not by itself imply more than one framework. The top-level `framework` field is deprecated; use `segments` for in-scope frameworks. This endpoint returns 404 for a soft-deleted audit. Rate limit: 250 requests / minute. # Get framework codes for an audit Source: https://developer.vanta.com/api-reference/audits/get-framework-codes-for-an-audit https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/framework-codes Retrieves all valid framework codes for the specified audit. This endpoint helps users discover which framework codes are available for creating and updating information requests for this audit. Use this endpoint to: - Discover available framework codes (`frameworkCodes`, the original flat list) - Validate framework codes against the audit's frameworks - See which codes belong to which in-scope framework (`codesByFramework`) Rate limit: 50 requests / minute. # Get information request evidence by ID Source: https://developer.vanta.com/api-reference/audits/get-information-request-evidence-by-id https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/information-requests/{requestId}/evidence/{evidenceId} Retrieves a single evidence item attached to an information request by its ID. This endpoint always includes soft-deleted evidence (where `deletionDate !== null`), so an evidence ID surfaced by a `changedSinceDate` delta sync stays fetchable after the evidence is deleted. Clients should check the `deletionDate` field to identify and handle deleted records appropriately in their systems. Evidence is only resolvable while its information request exists. Once the request itself is deleted, this endpoint returns a 4xx HTTP error instead of the evidence. Check the request's `deletionDate` using `GET /audits/{auditId}/information-requests` before treating its evidence as deleted too. Evidence that the customer has not shared with the auditor is reported as not found, rather than distinguishing it from an ID that does not exist. Rate limit: 250 requests / minute. # Get organization information for an audit Source: https://developer.vanta.com/api-reference/audits/get-organization-information-for-an-audit https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/organization/information Retrieves organization information for an audit. This endpoint returns a single record containing the organization's business information visible to auditors during an audit engagement. Sorting and pagination are not applicable. Rate limit: 10 requests / minute. # Get organization notification settings for an audit Source: https://developer.vanta.com/api-reference/audits/get-organization-notification-settings-for-an-audit https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/organization/notifications Retrieves organization notification settings for an audit. This endpoint returns a single record containing the auditee organization's notification configuration — schedule, personnel reminder settings, and external notification subscriptions (Compliance, Vendors, Access Reviews, Trust Center). The response is a single aggregate object per domain. Sorting and pagination are not applicable. Under a controlled audit view (TRIMMED_DOWN), only CAV-approved fields are included. Rate limit: 10 requests / minute. # Get test snapshot detail for an evidence row Source: https://developer.vanta.com/api-reference/audits/get-test-snapshot-detail-for-an-evidence-row https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/information-requests/{requestId}/evidence/{evidenceId}/test-snapshot Retrieves the rich detail for a single VANTA_TEST_SNAPSHOT evidence row attached to an information request. The response includes test-level metadata (description, integrations, SLA), the raw test data captured at snapshot time, and the resources that were excluded from the test (out-of-scope resources). For structured snapshots, the `rawTestData` array contains one row per resource the test ran against; each row carries `resourceId`, `resourceType`, and the raw JSON for that resource. For unstructured snapshots, the `rawTestData` array contains a single row with `resourceId` and `resourceType` set to `null` and `rawJson` containing the entire test-run JSON blob. The `outOfScopeResources` field lists resources excluded at the test level (customer-disabled) and the framework level (segment configuration). Empty exclusion groups are filtered out. The `apiRequests` array contains the HTTP requests captured during API introspection tests. Empty when the test does not perform API introspection. Rate limit: 10 requests / minute. # List account access records for an audit Source: https://developer.vanta.com/api-reference/audits/list-account-access-records-for-an-audit https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/personnel/account-access/{serviceId} Retrieves account access population data for an audit. This endpoint provides access to account access records visible to auditors during an audit engagement. Account access data comes from various sources: - **IDP Services** (Identity Providers): Okta, Azure AD, Google Workspace, OneLogin, PingOne - Returns user accounts from identity providers - Supports filtering by search and status - **Role Grants Services**: GCP, Azure (when role grants are enabled) - Returns accounts with role-based access grants - Supports filtering by search and status - **First-Party Account Services**: AWS, Oracle Cloud, Azure (when not using role grants), etc. - Returns cloud provider account access records - Supports filtering by search and status - **Received Account Services**: External applications (Jira, GitHub, Slack, etc.) - Returns user accounts from third-party integrations - Supports filtering by search and status Supports filtering by: - `search`: Searches account names/emails (case-insensitive) - `status`: Filters by account status Uses cursor-based pagination. To paginate: 1. Make initial request with desired `pageSize` 2. Check `results.pageInfo.hasNextPage` 3. Use `results.pageInfo.endCursor` as `pageCursor` for next request The default sort order depends on the service type: - Identity provider services (e.g. Okta, Azure AD): sorted by email, ascending - Cloud provider services (e.g. AWS, GCP): sorted by account name, ascending - Role grant services: sorted by account name, ascending - Third-party application services (e.g. GitHub, Jira): sorted by account name, ascending Sort order cannot be customized via query parameters. Returns 422 when the audit does not have exactly one program segment (multi-framework audits are not supported on this endpoint). Rate limit: 10 requests / minute. # List account access services for an audit Source: https://developer.vanta.com/api-reference/audits/list-account-access-services-for-an-audit https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/personnel/account-access/services Retrieves connected account access services for an audit. Returns the list of identity providers and access integrations (such as Okta, Azure AD, Google Workspace, AWS IAM) that are connected to the organization and provide account access data for personnel. These integrations are used to verify user access and identity management during an audit engagement. Uses cursor-based pagination. To paginate: 1. Make initial request with desired `pageSize` 2. Check `results.pageInfo.hasNextPage` 3. Use `results.pageInfo.endCursor` as `pageCursor` for next request Results are returned in connection order. Sort order is not guaranteed and cannot be customized via query parameters. Returns 422 when the audit does not have exactly one program segment (multi-framework audits are not supported on this endpoint). Rate limit: 10 requests / minute. # List assets associated with vulnerabilities Source: https://developer.vanta.com/api-reference/audits/list-assets-associated-with-vulnerabilities https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/vulnerable-assets List assets that Vanta monitors that are associated with vulnerabilities. End of life — this endpoint works for classic audits only; it does not support controlled audit view. It remains available for existing classic audits but will be removed once classic audits are fully phased out, so do not build new integrations on it. Rate limit: 10 requests / minute. # List audit comments Source: https://developer.vanta.com/api-reference/audits/list-audit-comments https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/comments Returns a paginated list of comments for an audit. Rate limit: 250 requests / minute. # List audit controls Source: https://developer.vanta.com/api-reference/audits/list-audit-controls https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/controls Returns a paginated list of controls for an audit. Rate limit: 250 requests / minute. # List audit evidence Source: https://developer.vanta.com/api-reference/audits/list-audit-evidence https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/evidence Returns a paginated list of evidence for an audit. Rate limit: 250 requests / minute. # List audit evidence url Source: https://developer.vanta.com/api-reference/audits/list-audit-evidence-url https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/evidence/{auditEvidenceId}/urls Returns a paginated list of evidence urls for an audit. This endpoint should be called whenever an evidence is created or has a statusUpdatedAt field that is more recent than the most recent polling event. Evidence must be in one of the following states to retrieve URLs: "Ready for audit", "Accepted", "Flagged", or "NA". Returns 422 when the audit does not have exactly one program segment (multi-framework audits are not supported on this endpoint). Rate limit: 600 requests / minute. # List audits Source: https://developer.vanta.com/api-reference/audits/list-audits https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits Returns a paginated list of audits scoped to the audit firm. To identify IRL (Information Request List) audits, check for the presence of the `auditorRequestListMetadata` field. This field is only present for IRL-based audits and will be `undefined` for standard audits. Each audit includes `segments`, the audit's scope. A live audit returns every in-scope program and system segment; more than one segment does not by itself imply more than one framework. The top-level `framework` field is deprecated; use `segments` for in-scope frameworks. This list may include soft-deleted audits so clients can reconcile deletions. Check `deletionDate`; a deleted audit has an empty `segments` list. Rate limit: 250 requests / minute. # List code changes for an audit Source: https://developer.vanta.com/api-reference/audits/list-code-changes-for-an-audit https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/assets/code-changes Retrieves code changes population data for an audit. This endpoint provides access to code change records (pull requests) visible to auditors during an audit engagement. Supports filtering by: - `search`: Searches code change titles and repository names (case-insensitive) - `sourcesMatchesAny`: Filters by version control source (accepted values: github, gitlab, bitbucket, azuredevops) - `closedAfterDate` / `closedBeforeDate`: Filters by the closed date range Uses cursor-based pagination. To paginate: 1. Make initial request with desired `pageSize` 2. Check `results.pageInfo.hasNextPage` 3. Use `results.pageInfo.endCursor` as `pageCursor` for next request Results are sorted by closed date (newest first). This sort order is fixed and cannot be customized via query parameters. Returns 422 when the audit does not have exactly one program segment (multi-framework audits are not supported on this endpoint). Rate limit: 10 requests / minute. # List comments for a control within an audit Source: https://developer.vanta.com/api-reference/audits/list-comments-for-a-control-within-an-audit https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/controls/{controlId}/comments Retrieves a paginated list of comments on a control within an IRL audit, enabling auditors to view collaboration history on the control. This endpoint always includes soft-deleted records (where `deletionDate !== null`). Clients should check the `deletionDate` field to identify and handle deleted records appropriately in their systems. This endpoint supports delta synchronization via the `changedSinceDate` parameter, allowing efficient polling for changes without retrieving the entire dataset. Returns 404 when the control is not part of the audit. Pagination usage: 1. Make initial request with desired `pageSize` 2. Check `results.pageInfo.hasNextPage` to see if more data exists 3. If true, use `results.pageInfo.endCursor` as `pageCursor` in next request 4. Repeat until `hasNextPage` is false Delta sync usage: 1. Store the timestamp of your last sync 2. Pass that timestamp as `changedSinceDate` 3. Only comments created, modified, or deleted since that timestamp are returned 4. Process updates, including soft-deletes (deletionDate !== null) 5. Update your last sync timestamp to the current time Rate limit: 50 requests / minute. # List comments for an information request Source: https://developer.vanta.com/api-reference/audits/list-comments-for-an-information-request https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/information-requests/{requestId}/comments Retrieves a paginated list of comments for an information request, enabling auditors to view communication history and collaborate with customers. This endpoint always includes soft-deleted records (where `deletionDate !== null`). Clients should check the `deletionDate` field to identify and handle deleted records appropriately in their systems. If the information request itself has been deleted, this endpoint returns a 4xx HTTP error instead of its comments. This endpoint supports delta synchronization via the `changedSinceDate` parameter, allowing efficient polling for changes without retrieving the entire dataset. Pagination usage: 1. Make initial request with desired `pageSize` 2. Check `results.pageInfo.hasNextPage` to see if more data exists 3. If true, use `results.pageInfo.endCursor` as `pageCursor` in next request 4. Repeat until `hasNextPage` is false Delta sync usage: 1. Store the timestamp of your last sync 2. Pass that timestamp as `changedSinceDate` 3. Only comments created, modified, or deleted since that timestamp are returned 4. Process updates, including soft-deletes (deletionDate !== null) 5. Update your last sync timestamp to the current time Rate limit: 50 requests / minute. # List evidence for an information request Source: https://developer.vanta.com/api-reference/audits/list-evidence-for-an-information-request https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/information-requests/{requestId}/evidence Retrieves a paginated list of all evidence attached to an information request, enabling auditors to review evidence submitted by customers. This endpoint always includes soft-deleted records (where `deletionDate !== null`). Clients should check the `deletionDate` field to identify and handle deleted records appropriately in their systems. If the information request itself has been deleted, this endpoint returns a 4xx HTTP error instead of its evidence. This endpoint supports delta synchronization via the `changedSinceDate` parameter, allowing efficient polling for changes without retrieving the entire dataset. Pagination usage: 1. Make initial request with desired `pageSize` 2. Check `results.pageInfo.hasNextPage` to see if more data exists 3. If true, use `results.pageInfo.endCursor` as `pageCursor` in next request 4. Repeat until `hasNextPage` is false Delta sync usage: 1. Store the timestamp of your last sync 2. Pass that timestamp as `changedSinceDate` 3. Only evidence created, modified, shared, or deleted since that timestamp is returned 4. Process updates, including soft-deletes (deletionDate !== null) 5. Update your last sync timestamp to the current time Rate limit: 50 requests / minute. # List groups for an audit Source: https://developer.vanta.com/api-reference/audits/list-groups-for-an-audit https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/personnel/groups Retrieves groups population data for an audit. This endpoint provides access to the group records visible to auditors during an audit engagement. Groups represent organizational units that contain people, either imported from an identity provider (IDP) or created manually in Vanta. Only Controlled Audit View (CAV) audits are supported. Full Audit View audits are rejected with 403. Supports filtering by: - `search`: Searches group names (case-insensitive) - `sourcesMatchesAny`: Filters by IDP source service names Results are sorted by name (ascending) by default. Use `orderBy` and `orderDirection` to customize sorting. Sort parameters must remain consistent across paginated requests. Uses cursor-based pagination. To paginate: 1. Make initial request with desired `pageSize` 2. Check `results.pageInfo.hasNextPage` 3. Use `results.pageInfo.endCursor` as `pageCursor` for next request Rate limit: 10 requests / minute. # List information request activity Source: https://developer.vanta.com/api-reference/audits/list-information-request-activity https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/information-requests/{requestId}/activity Retrieves a paginated list of activity logs for an information request, providing an audit trail of the changes and actions taken on it. Activity recording Vanta's automated preparation of a request is never returned by this endpoint, so `fillOutcome` is always null here. Some internal status transitions are also withheld, and those are removed after a page is selected, so a page can contain fewer entries than `pageSize` — or none at all — while more pages remain. Follow `results.pageInfo.hasNextPage` rather than treating a short or empty page as the end of the list. If the information request has been deleted, this endpoint returns a 4xx HTTP error instead of its activity. This endpoint supports delta synchronization via the `changedSinceDate` parameter, allowing efficient polling for changes without retrieving the entire dataset. Pagination usage: 1. Make initial request with desired `pageSize` 2. Check `results.pageInfo.hasNextPage` to see if more data exists 3. If true, use `results.pageInfo.endCursor` as `pageCursor` in next request 4. Repeat until `hasNextPage` is false Delta sync usage: 1. Store the timestamp of your last sync 2. Pass that timestamp as `changedSinceDate` 3. Only activity created since that timestamp is returned 4. Process updates to track all changes to the information request 5. Update your last sync timestamp to the current time Rate limit: 50 requests / minute. # List information requests for an audit Source: https://developer.vanta.com/api-reference/audits/list-information-requests-for-an-audit https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/information-requests Retrieves a paginated list of all information requests for an audit, enabling external audit management systems to display and track evidence requests. This endpoint always includes soft-deleted records (where `deletionDate !== null`). Clients should check the `deletionDate` field to identify and handle deleted records appropriately in their systems. This is the only endpoint that returns a deleted information request. No webhook fires when a request is deleted. Endpoints under `/audits/{auditId}/information-requests/{requestId}` return a 4xx HTTP error for a deleted request. To confirm deletion, check the request's `deletionDate` in this list. Deleting a request does not set `deletionDate` on its comments or evidence or send delete events for them. Once this list confirms the request was deleted, treat its comments and evidence as deleted too. This endpoint supports delta synchronization via the `changedSinceDate` parameter, allowing efficient polling for changes without retrieving the entire dataset. Pagination usage: 1. Make initial request with desired `pageSize` 2. Check `results.pageInfo.hasNextPage` to see if more data exists 3. If true, use `results.pageInfo.endCursor` as `pageCursor` in next request 4. Repeat until `hasNextPage` is false Delta sync usage: 1. Store the timestamp of your last sync 2. Pass that timestamp as `changedSinceDate` 3. Only requests created, modified, or deleted since that timestamp are returned 4. Process updates and soft-deletes by checking the `deletionDate` field 5. Update your last sync timestamp to the current time `segmentIds` on each returned request is resolved against the audit's current scope. A scope-only change (a segment leaving or joining the audit without the request row being written) is not a delta-sync event. Re-fetch without `changedSinceDate`, or GET by id, to see the current projection. Rate limit: 50 requests / minute. # List information requests linked to a control within an audit Source: https://developer.vanta.com/api-reference/audits/list-information-requests-linked-to-a-control-within-an-audit https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/controls/{controlId}/information-requests Returns a paginated list of active information requests linked to a specific control within an IRL audit. Only links saved on the audit's current control rows are included. Soft-deleted information requests are not included in the response. To synchronize deletions, use `GET /audits/{auditId}/information-requests`, which supports `changedSinceDate` and includes soft-deleted records. Returns 404 when the control is not part of the audit. Returns an empty page when the control is part of the audit but has no active IRLs linked to it. Pagination usage: 1. Make initial request with desired `pageSize` 2. Check `results.pageInfo.hasNextPage` to see if more data exists 3. If true, use `results.pageInfo.endCursor` as `pageCursor` in next request 4. Repeat until `hasNextPage` is false Rate limit: 50 requests / minute. # List integrations for an audit Source: https://developer.vanta.com/api-reference/audits/list-integrations-for-an-audit https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/integrations Retrieves integration population data for an audit. This endpoint provides access to integration records visible to auditors during an audit engagement. Integrations represent connected services (e.g., GitHub, AWS, Slack) that provide data for the audit. Supports filtering by: - `search`: Searches integration names (case-insensitive) - `tagsMatchesAny`: Filters by integration tag (ACCESS, COMPUTERS, etc.) - `categoriesMatchesAny`: Filters by category (CLOUD_PROVIDER, HR_PROVIDER, etc.) Uses cursor-based pagination. To paginate: 1. Make initial request with desired `pageSize` 2. Check `results.pageInfo.hasNextPage` 3. Use `results.pageInfo.endCursor` as `pageCursor` for next request Results are sorted by integration display name (ascending). This sort order is fixed and cannot be customized via query parameters. Rate limit: 10 requests / minute. # List monitored computers Source: https://developer.vanta.com/api-reference/audits/list-monitored-computers https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/monitored-computers Returns a list of computers monitored by an MDM (with an integration built by Vanta) or by Vanta Device Monitor. Currently this list does not include resources from partner or customer-built integrations. End of life — this endpoint works for classic audits only; it does not support controlled audit view. It remains available for existing classic audits but will be removed once classic audits are fully phased out, so do not build new integrations on it. Returns 422 when the audit does not have exactly one program segment (multi-framework audits are not supported on this endpoint). Rate limit: 10 requests / minute. # List of people who are in scope for this audit Source: https://developer.vanta.com/api-reference/audits/list-of-people-who-are-in-scope-for-this-audit https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/people Returns a list of people who are in scope for this audit. End of life — this endpoint works for classic audits only; it does not support controlled audit view. It remains available for existing classic audits but will be removed once classic audits are fully phased out, so do not build new integrations on it. Rate limit: 10 requests / minute. # List of vendors who are in scope for this audit Source: https://developer.vanta.com/api-reference/audits/list-of-vendors-who-are-in-scope-for-this-audit https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/vendors Returns a list of vendors who are in scope for this audit. End of life — this endpoint works for classic audits only; it does not support controlled audit view. It remains available for existing classic audits but will be removed once classic audits are fully phased out, so do not build new integrations on it. Rate limit: 10 requests / minute. # List people for an audit Source: https://developer.vanta.com/api-reference/audits/list-people-for-an-audit https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/personnel/people Retrieves people population data for an audit. This endpoint provides access to the people records visible to auditors during an audit engagement. Only Controlled Audit View (CAV) audits are supported. Full Audit View audits are rejected with 403. Supports filtering by: - `search`: Searches names and email addresses - `status`: Filters by employment status - `groupsMatchesAny`: Filter people by group/role IDs Results are sorted by name (ascending) by default. Use `orderBy` and `orderDirection` to customize sorting. Sort parameters must remain consistent across paginated requests. Uses cursor-based pagination. To paginate: 1. Make initial request with desired `pageSize` 2. Check `results.pageInfo.hasNextPage` 3. Use `results.pageInfo.endCursor` as `pageCursor` for next request Rate limit: 10 requests / minute. # List risk snapshots for an audit Source: https://developer.vanta.com/api-reference/audits/list-risk-snapshots-for-an-audit https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/risks/snapshots Returns a paginated list of risk assessment snapshots available for an audit. Risk snapshots capture the state of an organization's risk register at a point in time. Each snapshot has an `id` that can be used with the `/audits/{auditId}/risks` endpoint to retrieve the individual risk scenarios within that snapshot. Results are sorted by creation date (newest first). This sort order is fixed and cannot be customized via query parameters. Only snapshots that are shared with auditors are included. Uses cursor-based pagination. To paginate: 1. Make initial request with desired `pageSize` 2. Check `results.pageInfo.hasNextPage` 3. Use `results.pageInfo.endCursor` as `pageCursor` for next request Rate limit: 10 requests / minute. # List risks for an audit Source: https://developer.vanta.com/api-reference/audits/list-risks-for-an-audit https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/risks/{snapshotId} Retrieves risk population data for an audit. This endpoint provides access to the risk records visible to auditors during an audit engagement. Risk data is scoped to a specific risk assessment snapshot identified by the `snapshotId` parameter. Only Controlled Audit View (CAV) audits are supported. Full Audit View audits are rejected with 403. Supports filtering by: - `search`: Searches risk scenario descriptions (case-insensitive) Results are sorted by identified date (newest first) by default. Use `orderBy` and `orderDirection` to customize sorting. Sort parameters must remain consistent across paginated requests. Uses cursor-based pagination. To paginate: 1. Make initial request with desired `pageSize` 2. Check `results.pageInfo.hasNextPage` 3. Use `results.pageInfo.endCursor` as `pageCursor` for next request Rate limit: 10 requests / minute. # List snapshotted issues for an audit Source: https://developer.vanta.com/api-reference/audits/list-snapshotted-issues-for-an-audit https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/issues/items Retrieves a list of all issues that have been shared with an audit. The issues returned are immutable, point-in-time snapshots; there may be duplicates of issues that have been snapshotted at different times. The GET /audits/{auditId}/issues/snapshots endpoint can be used to retrieve metadata about the snapshots that issues belong to. Issues represent compliance findings from a variety of sources that need to be tracked and remediated. Supports filtering by: - `search`: full text search across issue title and description - `snapshotId`: filtering to a specific snapshot or snapshots, which represent point-in-time captures of issues. Use the GET /audits/{auditId}/issues/snapshots endpoint to retrieve snapshot IDs and metadata. - `createdAfterDate` / `createdBeforeDate`: filter to issues created within a date range (inclusive) - `detectedAfterDate` / `detectedBeforeDate`: filter to issues detected within a date range (inclusive) Results are sorted by issue creation date in descending order (newest first) by default. Use `orderBy` and `orderDirection` to customize sorting. Sort parameters must remain consistent across paginated requests. Uses cursor-based pagination. To paginate: 1. Make initial request with desired `pageSize` 2. Check `results.pageInfo.hasNextPage` 3. Use `results.pageInfo.endCursor` as `pageCursor` for next request Rate limit: 10 requests / minute. # List snapshotted issues for an audit Source: https://developer.vanta.com/api-reference/audits/list-snapshotted-issues-for-an-audit-1 https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/issues/snapshots Retrieves a list of snapshots that have been shared with an audit. The snapshots returned contain metadata about point-in-time captures of issues for an audit. This data can be used to filter down the list of issues to specific snapshots when querying the GET /audits/{auditId}/issues/items endpoint. Supports filtering by: - `search`: full text search across snapshot title and description Results are sorted by snapshot creation date in descending order (newest first). Uses cursor-based pagination. To paginate: 1. Make initial request with desired `pageSize` 2. Check `results.pageInfo.hasNextPage` 3. Use `results.pageInfo.endCursor` as `pageCursor` for next request Rate limit: 10 requests / minute. # List vendors for an audit Source: https://developer.vanta.com/api-reference/audits/list-vendors-for-an-audit https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/managed-vendors Retrieves vendor population data for an audit. This endpoint provides access to vendor records visible to auditors during an audit engagement. Supports filtering by: - `search`: Searches vendor names (case-insensitive) - `vendorStatusesMatchesAny`: Filters by vendor status (ACTIVE, ARCHIVED, IN_PROCUREMENT) - `inherentRiskMatchesAny`: Filters by inherent risk level Results are sorted by name (ascending) by default. Use `orderBy` and `orderDirection` to customize sorting. Sort parameters must remain consistent across paginated requests. Uses cursor-based pagination. To paginate: 1. Make initial request with desired `pageSize` 2. Check `results.pageInfo.hasNextPage` 3. Use `results.pageInfo.endCursor` as `pageCursor` for next request Rate limit: 10 requests / minute. # List vulnerabilities within the scope of a given audit Source: https://developer.vanta.com/api-reference/audits/list-vulnerabilities-within-the-scope-of-a-given-audit https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/vulnerabilities List all vulnerabilities based on selected filters. End of life — this endpoint works for classic audits only; it does not support controlled audit view. It remains available for existing classic audits but will be removed once classic audits are fully phased out, so do not build new integrations on it. Rate limit: 10 requests / minute. # List vulnerability remediations that are in scope for this audit Source: https://developer.vanta.com/api-reference/audits/list-vulnerability-remediations-that-are-in-scope-for-this-audit https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples get /audits/{auditId}/vulnerability-remediations List all vulnerability remediations based on selected filters that are in scope for this audit. End of life — this endpoint works for classic audits only; it does not support controlled audit view. It remains available for existing classic audits but will be removed once classic audits are fully phased out, so do not build new integrations on it. Returns 422 when the audit does not have exactly one program segment (multi-framework audits are not supported on this endpoint). Rate limit: 10 requests / minute. # Share information request list with customer Source: https://developer.vanta.com/api-reference/audits/share-information-request-list-with-customer https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples post /audits/{auditId}/share-information-request-list Shares the current information request list for an audit with the customer organization, making it visible in their portal. This action allows the customer to see all information requests that have been created for their audit. Only IRL audits are supported. Rate limit: 50 requests / minute. # Update a comment for a control within an audit Source: https://developer.vanta.com/api-reference/audits/update-a-comment-for-a-control-within-an-audit https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples patch /audits/{auditId}/controls/{controlId}/comments/{commentId} Updates an existing comment on a control. Only the original author of the comment can update it. The author is identified by their email address, which must match the email of the user who created the comment. Rate limit: 10 requests / minute. # Update a comment for an information request Source: https://developer.vanta.com/api-reference/audits/update-a-comment-for-an-information-request https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples patch /audits/{auditId}/information-requests/{requestId}/comments/{commentId} Updates an existing comment for an information request. Only the original author of the comment can update it. The author is identified by their email address, which must match the email of the user who created the comment. Rate limit: 25 requests / minute. # Update an information request for an audit Source: https://developer.vanta.com/api-reference/audits/update-an-information-request-for-an-audit https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples patch /audits/{auditId}/information-requests/{requestId} Updates an existing information request for an audit, allowing modification of request details as audit requirements evolve. Supports partial updates where only specified fields are changed; omitted fields remain unchanged. Common use cases: - Updating due dates as audit timelines shift - Refining descriptions to clarify requirements - Adjusting request type Note: The `modificationDate` is automatically updated to the current timestamp when any field is changed. Rate limit: 50 requests / minute. # Update audit evidence Source: https://developer.vanta.com/api-reference/audits/update-audit-evidence https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples patch /audits/{auditId}/evidence/{auditEvidenceId} Update audit evidence. Rate limit: 50 requests / minute. # Upsert a control's assessment within an audit Source: https://developer.vanta.com/api-reference/audits/upsert-a-controls-assessment-within-an-audit https://spec.speakeasy.com/vanta/vanta/conduct-an-audit-with-code-samples put /audits/{auditId}/controls/{controlId}/assessment Records (upserts) an auditor's assessment state and justification for a control within an IRL audit — the API equivalent of assessing a control in the web app. Overwrites the assessment for this control in the chosen audit segment. Which segments accept assessments depends on the audit's segments (see `segments[].kind` on the audit). If the audit has any `PROGRAM` segments, `segmentId` must be one of them; `SYSTEM` segment IDs are rejected, even on an audit that also has system segments. If the audit has only `SYSTEM` segments, `segmentId` must be one of those. `segmentId` may be omitted only when exactly one segment accepts assessments. The `assessmentState` must be valid for that segment's framework (the request is rejected otherwise). The acting auditor is identified by `auditorEmail`, which must belong to the audit firm making the request. Returns 404 when the control is not part of the audit or the auditor email does not resolve to a firm user. Returns 422 when `segmentId` is omitted but more than one segment accepts assessments, when `segmentId` is not a segment on this audit that accepts assessments, or when the control is not assigned to that segment for this audit. Applies to both Full and Controlled Audit View audits. Rate limit: 10 requests / minute. # List all Background Checks Source: https://developer.vanta.com/api-reference/background-checks/list-all-background-checks /reference/build-integrations.json get /v1/resources/background_check_connector List `BackgroundCheckConnector` resources for the given application. ** Headers ** ``` Authorization: Bearer ``` ** Scopes ** ``` connectors.self:read-resource ``` # Sync all Background Checks Source: https://developer.vanta.com/api-reference/background-checks/sync-all-background-checks /reference/build-integrations.json put /v1/resources/background_check_connector To send us data regarding employee/contractor background checks, you send us `BackgroundCheckConnector` resources. This helps us determine current background check statuses. This call replaces ALL existing `BackgroundCheckConnector` resources for the given app and `source_id` - this is a "state of the world" sync. In other words, if a `BackgroundCheckConnector` resource is sent for a user in a previous `sync_all` call, but is not included in a later `sync_all` call for that customer, it is assumed to no longer exist and is deleted in Vanta. ** Headers ** ``` Authorization: Bearer ``` ** Scopes ** ``` connectors.self:write-resource ``` ** Schema ** Expand the `resources` array below for the schema of `BackgroundCheckConnector`. # Get business unit by ID Source: https://developer.vanta.com/api-reference/business-units/get-business-unit-by-id /reference/manage-vanta.json get /business-units/{businessUnitId} Get a business unit by ID. Returns 403 when business unit scoping is disabled for the domain. # List business units Source: https://developer.vanta.com/api-reference/business-units/list-business-units /reference/manage-vanta.json get /business-units Lists the business units for your organization. Returns 403 when business unit scoping is disabled for the domain. # Delete contract Source: https://developer.vanta.com/api-reference/contracts/delete-contract /reference/manage-vanta.json delete /contracts/{contractId} Delete a contract by ID. # Get contract Source: https://developer.vanta.com/api-reference/contracts/get-contract /reference/manage-vanta.json get /contracts/{contractId} Get a contract by ID. # List contracts Source: https://developer.vanta.com/api-reference/contracts/list-contracts /reference/manage-vanta.json get /contracts List contracts, paginated. # Upload contract Source: https://developer.vanta.com/api-reference/contracts/upload-contract /reference/manage-vanta.json post /contracts Upload a contract. Rate limit: 10 requests / minute. # Control comment created Source: https://developer.vanta.com/api-reference/control/control-comment-created /reference/webhooks.json post /v1.control.comment.created An external comment was created on an audit control. Fires once per comment. This event is delivered only to [Audit Partner](/reference/audits/overview) accounts and is gated by the early-access `audit_control_comment_webhook` feature — reach out to your Vanta contact to enable it. The payload contains only identifiers. Fetch the comment body from `GET /v1/audits/{auditId}/controls/{controlId}/comments`. # Control comment deleted Source: https://developer.vanta.com/api-reference/control/control-comment-deleted /reference/webhooks.json post /v1.control.comment.deleted An external comment was deleted from an audit control. Fires once per comment deletion. This event is delivered only to [Audit Partner](/reference/audits/overview) accounts and is gated by the early-access `audit_control_comment_webhook` feature — reach out to your Vanta contact to enable it. The payload contains only identifiers. The deleted comment no longer appears in `GET /v1/audits/{auditId}/controls/{controlId}/comments`. # Control comment updated Source: https://developer.vanta.com/api-reference/control/control-comment-updated /reference/webhooks.json post /v1.control.comment.updated An external comment on an audit control was updated. Fires once per comment update. This event is delivered only to [Audit Partner](/reference/audits/overview) accounts and is gated by the early-access `audit_control_comment_webhook` feature — reach out to your Vanta contact to enable it. The payload contains only identifiers. Fetch the current comment body from `GET /v1/audits/{auditId}/controls/{controlId}/comments`. # Add control from Vanta library Source: https://developer.vanta.com/api-reference/controls/add-control-from-vanta-library /reference/manage-vanta.json post /controls/add-from-library Add a control from the Vanta library to your organization's controls. # Add control to document mapping Source: https://developer.vanta.com/api-reference/controls/add-control-to-document-mapping /reference/manage-vanta.json post /controls/{controlId}/add-document-to-control Add a document to a control. # Add control to test mapping Source: https://developer.vanta.com/api-reference/controls/add-control-to-test-mapping /reference/manage-vanta.json post /controls/{controlId}/add-test-to-control Add a control to test mapping. # Create custom control Source: https://developer.vanta.com/api-reference/controls/create-custom-control /reference/manage-vanta.json post /controls Create a custom control. # Deactivates a control Source: https://developer.vanta.com/api-reference/controls/deactivates-a-control /reference/manage-vanta.json delete /controls/{controlId} Deactivates a custom or Vanta control. # Get control by an ID Source: https://developer.vanta.com/api-reference/controls/get-control-by-an-id /reference/manage-vanta.json get /controls/{controlId} Get a control by an ID. # List a control's documents Source: https://developer.vanta.com/api-reference/controls/list-a-controls-documents /reference/manage-vanta.json get /controls/{controlId}/documents List a control's documents. # List a control's tests Source: https://developer.vanta.com/api-reference/controls/list-a-controls-tests /reference/manage-vanta.json get /controls/{controlId}/tests List a control's tests. # List controls Source: https://developer.vanta.com/api-reference/controls/list-controls /reference/manage-vanta.json get /controls List controls. # List deactivated controls Source: https://developer.vanta.com/api-reference/controls/list-deactivated-controls /reference/manage-vanta.json get /controls/deactivated-controls List deactivated Vanta controls (previously known as the controls library). # List Vanta controls from the library Source: https://developer.vanta.com/api-reference/controls/list-vanta-controls-from-the-library /reference/manage-vanta.json get /controls/controls-library List Vanta controls from the library. # Remove control from document mapping Source: https://developer.vanta.com/api-reference/controls/remove-control-from-document-mapping /reference/manage-vanta.json delete /controls/{controlId}/documents/{documentId} Remove a document by ID from a control. # Remove control from test mapping Source: https://developer.vanta.com/api-reference/controls/remove-control-from-test-mapping /reference/manage-vanta.json delete /controls/{controlId}/tests/{testId} Remove a control from test mapping. # Set owner of a control Source: https://developer.vanta.com/api-reference/controls/set-owner-of-a-control /reference/manage-vanta.json post /controls/{controlId}/set-owner Assign a control to a user or remove an owner from a control. # Update a control's metadata Source: https://developer.vanta.com/api-reference/controls/update-a-controls-metadata /reference/manage-vanta.json patch /controls/{controlId} Update a control's metadata. # List all Custom Resources Source: https://developer.vanta.com/api-reference/custom-resources/list-all-custom-resources /reference/build-integrations.json get /v1/resources/custom_resource List `CustomResource` resources for the given application. ** Headers ** ``` Authorization: Bearer ``` ** Scopes ** ``` connectors.self:read-resource ``` # Sync all Custom Resources Source: https://developer.vanta.com/api-reference/custom-resources/sync-all-custom-resources /reference/build-integrations.json put /v1/resources/custom_resource To send data of custom resource that you want to build custom tests on, use `CustomResource`. This call replaces ALL existing `CustomResource` resources for the given app and `source_id` - this is a "state of the world" sync. In other words, if a `CustomResource` resource is sent for a user in a previous `sync_all` call, but is not included in a later `sync_all` call for that customer, it is assumed to no longer exist and is deleted in Vanta. ** Headers ** ``` Authorization: Bearer ``` ** Scopes ** ``` connectors.self:write-resource ``` ** Schema ** Expand the `resources` array below for the schema of `CustomResource`. # Approve questionnaire Source: https://developer.vanta.com/api-reference/customer-trust/approve-questionnaire /reference/manage-vanta.json post /customer-trust/questionnaires/{questionnaireId}/approve Mark a questionnaire as `APPROVED` and optionally provide a `statusChangeMessage`. # Complete questionnaire Source: https://developer.vanta.com/api-reference/customer-trust/complete-questionnaire /reference/manage-vanta.json post /customer-trust/questionnaires/{questionnaireId}/complete Complete a questionnaire and optionally sync approved answers to the answer library. Transitions the questionnaire status to COMPLETE. If `shouldSyncApprovedToAnswerLibrary` is true (the default), approved answers are added to the answer library for future use. For non-English SPREADSHEET or DOCUMENT questionnaires, answer library sync will be ignored. # Create customer trust account Source: https://developer.vanta.com/api-reference/customer-trust/create-customer-trust-account /reference/manage-vanta.json post /customer-trust/accounts Create a new customer trust account. # Create data deletion request Source: https://developer.vanta.com/api-reference/customer-trust/create-data-deletion-request /reference/manage-vanta.json post /customer-trust/deletion-requests Submit a Right to Be Forgotten (RTBF) data deletion request for the specified email address. # Create file questionnaire Source: https://developer.vanta.com/api-reference/customer-trust/create-file-questionnaire /reference/manage-vanta.json post /customer-trust/questionnaires/file Create a new file-based questionnaire from an uploaded file (.xlsx, .docx, .pdf). File type is inferred as `SPREADSHEET` or `DOCUMENT` based on the uploaded file. # Create questionnaire export Source: https://developer.vanta.com/api-reference/customer-trust/create-questionnaire-export /reference/manage-vanta.json post /customer-trust/questionnaires/exports Creates an asynchronous export job for a questionnaire. The export processes in the background and typically completes within a few minutes depending on questionnaire size. Subscribe to the `v1.questionnaire.export-completed` and `v1.questionnaire.export-failed` webhook events to be notified when an export completes or fails. Use the returned `id` with the "getQuestionnaireExport" endpoint to retrieve the download URL once the export completes. # Create website questionnaire Source: https://developer.vanta.com/api-reference/customer-trust/create-website-questionnaire /reference/manage-vanta.json post /customer-trust/questionnaires/website Create a new website-based questionnaire from a portal URL. The portal URL is used to fetch questionnaire content from the target website. # Delete customer trust account Source: https://developer.vanta.com/api-reference/customer-trust/delete-customer-trust-account /reference/manage-vanta.json delete /customer-trust/accounts/{accountId} Delete a customer trust account by ID. # Delete questionnaire Source: https://developer.vanta.com/api-reference/customer-trust/delete-questionnaire /reference/manage-vanta.json delete /customer-trust/questionnaires/{questionnaireId} Delete a questionnaire by ID. # Disable tag category for product context Source: https://developer.vanta.com/api-reference/customer-trust/disable-tag-category-for-product-context /reference/manage-vanta.json delete /customer-trust/tag-categories/{tagCategoryId}/product-contexts/{productContextId} Disables a tag category for a product context. Idempotent: removing a category that isn't enabled for the context is a no-op. # Enable tag category for product context Source: https://developer.vanta.com/api-reference/customer-trust/enable-tag-category-for-product-context /reference/manage-vanta.json post /customer-trust/tag-categories/{tagCategoryId}/product-contexts Enables a tag category for a product context (e.g. document sharing, control sharing), making it available for scoping that context's shareable content. Idempotent: enabling an already-enabled category is a no-op. # Get customer trust account Source: https://developer.vanta.com/api-reference/customer-trust/get-customer-trust-account /reference/manage-vanta.json get /customer-trust/accounts/{accountId} Get a specific customer trust account by ID. # Get questionnaire by ID Source: https://developer.vanta.com/api-reference/customer-trust/get-questionnaire-by-id /reference/manage-vanta.json get /customer-trust/questionnaires/{questionnaireId} Retrieve a questionnaire by ID. # Get questionnaire export status Source: https://developer.vanta.com/api-reference/customer-trust/get-questionnaire-export-status /reference/manage-vanta.json get /customer-trust/questionnaires/exports/{id} Retrieves the current status and result of a questionnaire export using the id received from either the `createQuestionnaireExport` endpoint or the `v1.questionnaire.export-completed` webhook payload. This endpoint utilizes a dynamic response schema that changes based on the value of the status field: - pending: The export is currently in the queue or processing. Only base metadata is returned. - completed: The export finished successfully. The response expands to include completedAt and a downloadUrl. This pre-signed URL is valid for 24 hours; if it expires, simply call this endpoint again to retrieve a fresh, active link. - failed: The process encountered an error. The response expands to include failedAt and an errorMessage detailing the reason for failure. Developers should first check the status string before attempting to access result-specific fields like downloadUrl or errorMessage. # Get questionnaire response Source: https://developer.vanta.com/api-reference/customer-trust/get-questionnaire-response /reference/manage-vanta.json get /customer-trust/questionnaires/{questionnaireId}/responses/{responseId} Retrieve a single questionnaire response. # Get tags for category Source: https://developer.vanta.com/api-reference/customer-trust/get-tags-for-category /reference/manage-vanta.json get /customer-trust/tag-categories/{tagCategoryId} Retrieve a tag category and its associated tags by category ID. # List assignable users Source: https://developer.vanta.com/api-reference/customer-trust/list-assignable-users /reference/manage-vanta.json get /customer-trust/questionnaires/assignable-users List users who can be assigned as owner or approver on a questionnaire. When a role is specified, results are filtered to users with that role's required permission. When omitted, users assignable to either role are returned. Results can optionally be narrowed by a search string. # List customer trust accounts Source: https://developer.vanta.com/api-reference/customer-trust/list-customer-trust-accounts /reference/manage-vanta.json get /customer-trust/accounts List customer trust accounts with pagination. # List questionnaire responses Source: https://developer.vanta.com/api-reference/customer-trust/list-questionnaire-responses /reference/manage-vanta.json get /customer-trust/questionnaires/{questionnaireId}/responses List the responses on a questionnaire. Each response carries its `answerPartsSchema` and `answerPartsValues`, which describe the parts an answer is composed of and their current values. # List questionnaires Source: https://developer.vanta.com/api-reference/customer-trust/list-questionnaires /reference/manage-vanta.json get /customer-trust/questionnaires List questionnaires with filtering and pagination. # List tag categories Source: https://developer.vanta.com/api-reference/customer-trust/list-tag-categories /reference/manage-vanta.json get /customer-trust/tag-categories List user-defined tag categories. Optionally filter by product context. # Update customer trust account Source: https://developer.vanta.com/api-reference/customer-trust/update-customer-trust-account /reference/manage-vanta.json patch /customer-trust/accounts/{accountId} Update a customer trust account by ID. # Update questionnaire Source: https://developer.vanta.com/api-reference/customer-trust/update-questionnaire /reference/manage-vanta.json patch /customer-trust/questionnaires/{questionnaireId} Update an existing questionnaire. Updates one or more fields of a questionnaire. This endpoint cannot be used to set a questionnaire's status to `APPROVED` or `COMPLETED`. To perform those specific transitions, please use the `approveQuestionnaire` and `completeQuestionnaire` endpoints, respectively. # Update questionnaire response content Source: https://developer.vanta.com/api-reference/customer-trust/update-questionnaire-response-content /reference/manage-vanta.json patch /customer-trust/questionnaires/{questionnaireId}/responses/{responseId} Update the answer content of a questionnaire response. The edit is recorded as performed by the calling application, since vanta-api authenticates an OAuth client rather than a specific user. # Update questionnaire response owner Source: https://developer.vanta.com/api-reference/customer-trust/update-questionnaire-response-owner /reference/manage-vanta.json patch /customer-trust/questionnaires/{questionnaireId}/responses/{responseId}/owner Reassign or clear the owner of a questionnaire response. The assignment is recorded as performed by the calling API client, so the notification to the new owner names the Vanta API rather than a user. # Adds a discovered vendor to managed vendor by ID Source: https://developer.vanta.com/api-reference/discovered-vendors/adds-a-discovered-vendor-to-managed-vendor-by-id /reference/manage-vanta.json post /discovered-vendors/{discoveredVendorId}/add-to-managed Add a discovered vendor to managed vendor. # List discovered vendors Source: https://developer.vanta.com/api-reference/discovered-vendors/list-discovered-vendors /reference/manage-vanta.json get /discovered-vendors List discovered vendors. # List of discovered vendor accounts Source: https://developer.vanta.com/api-reference/discovered-vendors/list-of-discovered-vendor-accounts /reference/manage-vanta.json get /discovered-vendors/{discoveredVendorId}/accounts List of discovered vendor accounts. # Create a custom document Source: https://developer.vanta.com/api-reference/documents/create-a-custom-document /reference/manage-vanta.json post /documents Create a custom document. # Create document link Source: https://developer.vanta.com/api-reference/documents/create-document-link /reference/manage-vanta.json post /documents/{documentId}/links Create a link for a document. # Delete document by ID Source: https://developer.vanta.com/api-reference/documents/delete-document-by-id /reference/manage-vanta.json delete /documents/{documentId} Delete a document by ID. # Delete file for a document Source: https://developer.vanta.com/api-reference/documents/delete-file-for-a-document /reference/manage-vanta.json delete /documents/{documentId}/uploads/{uploadedFileId} Delete a file for a document. # Download file for document Source: https://developer.vanta.com/api-reference/documents/download-file-for-document /reference/manage-vanta.json get /documents/{documentId}/uploads/{uploadedFileId}/media Download a file from a document. # Get document by ID Source: https://developer.vanta.com/api-reference/documents/get-document-by-id /reference/manage-vanta.json get /documents/{documentId} Get a document by ID. # List documents Source: https://developer.vanta.com/api-reference/documents/list-documents /reference/manage-vanta.json get /documents List documents. # List document's controls Source: https://developer.vanta.com/api-reference/documents/list-documents-controls /reference/manage-vanta.json get /documents/{documentId}/controls List a document's associated controls. # List document's links Source: https://developer.vanta.com/api-reference/documents/list-documents-links /reference/manage-vanta.json get /documents/{documentId}/links List the uploaded links for a document. # List document's uploads Source: https://developer.vanta.com/api-reference/documents/list-documents-uploads /reference/manage-vanta.json get /documents/{documentId}/uploads List the uploaded files for a document. # Remove document link Source: https://developer.vanta.com/api-reference/documents/remove-document-link /reference/manage-vanta.json delete /documents/{documentId}/links/{linkId} Remove a link from a document. # Set document owner Source: https://developer.vanta.com/api-reference/documents/set-document-owner /reference/manage-vanta.json post /documents/{documentId}/set-owner Assign or unassign a user to the document. # Submit document collection Source: https://developer.vanta.com/api-reference/documents/submit-document-collection /reference/manage-vanta.json post /documents/{documentId}/submit Submit document collection. # Upload file for document Source: https://developer.vanta.com/api-reference/documents/upload-file-for-document /reference/build-integrations.json post /v1/documents/{documentId}/uploads Upload a file for a document. # List event logs Source: https://developer.vanta.com/api-reference/event-logs/list-event-logs /reference/manage-vanta.json get /event-logs List event logs. See the [event log reference](/reference/manage-vanta/event-log-reference) for an inexhaustive list of `actor.type`, `action`, and `targets[].type` values. # Evidence comment created Source: https://developer.vanta.com/api-reference/evidence/evidence-comment-created /reference/webhooks.json post /v1.evidence.comment.created Fires when a comment is created on an audit evidence item. Fires once per comment. # Evidence comment deleted Source: https://developer.vanta.com/api-reference/evidence/evidence-comment-deleted /reference/webhooks.json post /v1.evidence.comment.deleted Fires when a comment is deleted from an audit evidence item. Fires once per comment deletion. # Evidence comment updated Source: https://developer.vanta.com/api-reference/evidence/evidence-comment-updated /reference/webhooks.json post /v1.evidence.comment.updated Fires when a comment on an audit evidence item is updated. Fires once per comment update. # Evidence created Source: https://developer.vanta.com/api-reference/evidence/evidence-created /reference/webhooks.json post /v1.evidence.created Fires when an audit evidence item comes into scope for an audit, including when a previously removed item re-enters scope after soft-delete. Evidence items are derived from the customer's compliance program, so this event means "a new item is now in scope for this audit", not "a customer uploaded a file". A brand-new item starts in `NOT_READY_FOR_AUDIT` with no files; wait for [`v1.evidence.status-changed`](/api-reference/evidence/evidence-status-changed) before requesting URLs. A re-scoped item retains its previous status and files. It may already be in `READY_FOR_AUDIT` or another state, and no follow-up status-change event is guaranteed. **This event does not replace the initial sync.** Items can come into scope from the moment the audit exists, which is normally before your access to the audit begins, and events from before that point are not delivered or replayed. Always perform a full traversal of `GET /audits/{auditId}/evidence` when you first pick up an audit, then rely on this event for items that come into scope afterwards. # Evidence deleted Source: https://developer.vanta.com/api-reference/evidence/evidence-deleted /reference/webhooks.json post /v1.evidence.deleted Fires when an audit evidence item leaves scope for an audit. Fires once per item. The item is soft-deleted rather than removed: `GET /audits/{auditId}/evidence` still returns it, with a non-null `deletionDate`. Stop requesting URLs for the item. If the item later returns to scope, Vanta emits a fresh [`v1.evidence.created`](/api-reference/evidence/evidence-created) event and clears `deletionDate`. # Evidence status changed Source: https://developer.vanta.com/api-reference/evidence/evidence-status-changed /reference/webhooks.json post /v1.evidence.status-changed Fires when an existing audit evidence item changes status. `oldStatus` and `newStatus` always describe a transition of an item that already exists. See [`v1.evidence.created`](/api-reference/evidence/evidence-created) for the event that fires when an item first comes into scope for an audit. **Ready-to-review signal:** a `newStatus` of `READY_FOR_AUDIT` means the customer has provided evidence for the item and it is ready for the auditor to review. **When it fires:** once per evidence item, each time its status changes. Status can also change on its own as the customer's compliance posture changes, so an item may move from `READY_FOR_AUDIT` back to `NOT_READY_FOR_AUDIT` without an explicit auditor action. `oldStatus` and `newStatus` can be equal. A newly detected document re-fires this event with both fields set to the item's current status (for example, `READY_FOR_AUDIT`, `ACCEPTED`, or `FLAGGED`). Treat that as a signal that the item's files may have changed and re-fetch its URLs. Do not discard events where the status is unchanged. **Status values:** - `NOT_READY_FOR_AUDIT` — the item is not yet ready for the auditor; required evidence is missing or does not meet the requirement. - `READY_FOR_AUDIT` — the customer has provided the evidence and it is ready for the auditor to review. - `ACCEPTED` — the auditor reviewed the item and accepted it. - `FLAGGED` — the auditor reviewed the item and flagged an issue for the customer to address; once the customer addresses it the item returns to `READY_FOR_AUDIT`. - `NA` — the item is not applicable to this audit. A typical lifecycle is `NOT_READY_FOR_AUDIT → READY_FOR_AUDIT → ACCEPTED` (or `→ FLAGGED`, which returns to `READY_FOR_AUDIT` once the customer addresses the issue). `INITIALIZED` is an internal status and is never delivered — `oldStatus` and `newStatus` are always one of the values above. # Get framework by ID Source: https://developer.vanta.com/api-reference/frameworks/get-framework-by-id /reference/manage-vanta.json get /frameworks/{frameworkId} Get a framework by ID. # List a framework's controls Source: https://developer.vanta.com/api-reference/frameworks/list-a-frameworks-controls /reference/manage-vanta.json get /frameworks/{frameworkId}/controls List a framework's controls. # List available frameworks Source: https://developer.vanta.com/api-reference/frameworks/list-available-frameworks /reference/manage-vanta.json get /frameworks Lists available frameworks. # Add people to group Source: https://developer.vanta.com/api-reference/groups/add-people-to-group /reference/manage-vanta.json post /groups/{groupId}/add-people Add people to a group. # Add person to a group Source: https://developer.vanta.com/api-reference/groups/add-person-to-a-group /reference/manage-vanta.json post /groups/{groupId}/people Add a single person, by ID, to a group. # Create group Source: https://developer.vanta.com/api-reference/groups/create-group /reference/manage-vanta.json post /groups Creates a group. # Get group by ID Source: https://developer.vanta.com/api-reference/groups/get-group-by-id /reference/manage-vanta.json get /groups/{groupId} Get a group by ID. # Import IdP groups Source: https://developer.vanta.com/api-reference/groups/import-idp-groups /reference/manage-vanta.json post /groups/import-from-idp Imports groups from an identity provider. # List groups Source: https://developer.vanta.com/api-reference/groups/list-groups /reference/manage-vanta.json get /groups Lists all groups by ID. # List importable IdP groups Source: https://developer.vanta.com/api-reference/groups/list-importable-idp-groups /reference/manage-vanta.json get /groups/importable-idp-groups Lists IdP groups that are available to import. # List people in a group Source: https://developer.vanta.com/api-reference/groups/list-people-in-a-group /reference/manage-vanta.json get /groups/{groupId}/people List people in a group. # Remove people from group Source: https://developer.vanta.com/api-reference/groups/remove-people-from-group /reference/manage-vanta.json post /groups/{groupId}/remove-people Remove people from a group. # Remove person from a group Source: https://developer.vanta.com/api-reference/groups/remove-person-from-a-group /reference/manage-vanta.json delete /groups/{groupId}/people/{personId} Remove a single person, by ID, from a group. # Update group Source: https://developer.vanta.com/api-reference/groups/update-group /reference/manage-vanta.json patch /groups/{groupId} Partially updates a group. At least one field must be provided. # Information request comment created Source: https://developer.vanta.com/api-reference/information-request/information-request-comment-created /reference/webhooks.json post /v1.information-request.comment.created Fires when a comment is created on an information request. Fires once per comment. Fetch the comment body with `GET /v1/audits/{auditId}/information-requests/{requestId}/comments/{commentId}`. The information request may be deleted between this event and your fetch. If the fetch returns a 4xx HTTP error, check the request's `deletionDate` in the information-request list. If set, treat the request and all its comments and evidence as deleted in your system. # Information request comment deleted Source: https://developer.vanta.com/api-reference/information-request/information-request-comment-deleted /reference/webhooks.json post /v1.information-request.comment.deleted Fires once when a comment is deleted from an information request. Remove the comment from your system using the IDs in this event. # Information request comment updated Source: https://developer.vanta.com/api-reference/information-request/information-request-comment-updated /reference/webhooks.json post /v1.information-request.comment.updated Fires when a comment on an information request is updated. Fires once per comment update. Fetch the comment body with `GET /v1/audits/{auditId}/information-requests/{requestId}/comments/{commentId}`. The information request may be deleted between this event and your fetch. If the fetch returns a 4xx HTTP error, check the request's `deletionDate` in the information-request list. If set, treat the request and all its comments and evidence as deleted in your system. # Information request evidence created Source: https://developer.vanta.com/api-reference/information-request/information-request-evidence-created /reference/webhooks.json post /v1.information-request.evidence.created Fires when a piece of evidence is added to an information request. Fires once per piece of evidence — if several pieces are added in a single action, you receive one event per piece. These `v1.information-request.evidence.*` events belong to the Information Request experience and are unrelated to the `v1.evidence.*` classic audit evidence events. # Information request evidence deleted Source: https://developer.vanta.com/api-reference/information-request/information-request-evidence-deleted /reference/webhooks.json post /v1.information-request.evidence.deleted Fires when a piece of evidence is removed from an information request. Fires once per piece of evidence removed. These `v1.information-request.evidence.*` events belong to the Information Request experience and are unrelated to the `v1.evidence.*` classic audit evidence events. # Information request status changed Source: https://developer.vanta.com/api-reference/information-request/information-request-status-changed /reference/webhooks.json post /v1.information-request.status-changed Fires when an information request's approval status changes. This is a status-change event. **Ready-to-review signal:** a `newStatus` of `READY_FOR_AUDIT` means the customer has submitted the information request and it is ready for the auditor to review. **When it fires:** once per information request, each time its status changes between the values below. Not every status transition emits an event. **Status values:** - `NEEDS_EVIDENCE` — the request still needs work from the customer; it is not yet ready for the auditor. - `READY_FOR_AUDIT` — the customer has submitted the request and it is ready for the auditor to review. - `AUDITOR_APPROVED` — the auditor reviewed the request and approved it. - `AUDITOR_FLAGGED` — the auditor flagged the request for the customer to address. A typical lifecycle is `NEEDS_EVIDENCE → READY_FOR_AUDIT → AUDITOR_APPROVED` (or `→ AUDITOR_FLAGGED`). A request can also move from `READY_FOR_AUDIT` back to `NEEDS_EVIDENCE` when the customer takes it back to continue working on it. # Get a connected integration Source: https://developer.vanta.com/api-reference/integrations/get-a-connected-integration /reference/manage-vanta.json get /integrations/{integrationId} Gets details for a specific integration by connection ID. # Get details for resource kind Source: https://developer.vanta.com/api-reference/integrations/get-details-for-resource-kind /reference/manage-vanta.json get /integrations/{integrationId}/resource-kinds/{resourceKind} Gets details for a specific resource type (kind) such as S3Bucket or CloudwatchLogGroup. # Get resource by ID Source: https://developer.vanta.com/api-reference/integrations/get-resource-by-id /reference/manage-vanta.json get /integrations/{integrationId}/resource-kinds/{resourceKind}/resources/{resourceId} Gets resource by its ID. # List connected integrations Source: https://developer.vanta.com/api-reference/integrations/list-connected-integrations /reference/manage-vanta.json get /integrations Lists all integrations connected to a Vanta instance. # List integration resource kinds Source: https://developer.vanta.com/api-reference/integrations/list-integration-resource-kinds /reference/manage-vanta.json get /integrations/{integrationId}/resource-kinds Lists a connected integration's resource types (kinds) such as S3Bucket or CloudwatchLogGroup. # List resources Source: https://developer.vanta.com/api-reference/integrations/list-resources /reference/manage-vanta.json get /integrations/{integrationId}/resource-kinds/{resourceKind}/resources Lists resources for a specific integration and resource type (kind) such as S3Bucket or CloudwatchLogGroup. # Update resource metadata Source: https://developer.vanta.com/api-reference/integrations/update-resource-metadata /reference/manage-vanta.json patch /integrations/{integrationId}/resource-kinds/{resourceKind}/resources Updates metadata for multiple resources. # Update resource metadata Source: https://developer.vanta.com/api-reference/integrations/update-resource-metadata-1 /reference/manage-vanta.json patch /integrations/{integrationId}/resource-kinds/{resourceKind}/resources/{resourceId} Updates metadata for a specific resource such as an S3Bucket or CloudwatchLogGroup. # Get issue by ID Source: https://developer.vanta.com/api-reference/issues/get-issue-by-id /reference/manage-vanta.json get /issues/{issueId} Get the details of an issue by its ID. # List issues Source: https://developer.vanta.com/api-reference/issues/list-issues /reference/manage-vanta.json get /issues List issues on a domain (paginated). Returns a paginated list of issues that the authenticated app has permission to view, optionally filtered and sorted. # Create Answer Library entry Source: https://developer.vanta.com/api-reference/knowledge-base/create-answer-library-entry /reference/manage-vanta.json post /knowledge-base/answer-library Create an Answer Library entry. # Create document resource Source: https://developer.vanta.com/api-reference/knowledge-base/create-document-resource /reference/manage-vanta.json post /knowledge-base/resources/documents Create a document (FILE-type) resource in the Trust Knowledge Base. Accepts the document as a multipart/form-data upload. Example: send `multipart/form-data` with a required `file` (e.g. PDF) and `title`; optional fields include `description`, `customerVisibility`, `downloadPermission`, `isUsedInQuestionnaires` ("true"/"false"), `expirationDate` (ISO 8601), `tags` (JSON array string), `categoryId`, and `ownerAssignment` (JSON object string). # Create webpage resource Source: https://developer.vanta.com/api-reference/knowledge-base/create-webpage-resource /reference/manage-vanta.json post /knowledge-base/resources/webpages Create a webpage (URL-type) resource in the Trust Knowledge Base. # Delete Answer Library entry Source: https://developer.vanta.com/api-reference/knowledge-base/delete-answer-library-entry /reference/manage-vanta.json delete /knowledge-base/answer-library/{id} Delete an Answer Library entry. # Delete Knowledge Base resource Source: https://developer.vanta.com/api-reference/knowledge-base/delete-knowledge-base-resource /reference/manage-vanta.json delete /knowledge-base/resources/{id} Hard-delete a Knowledge Base resource (FILE or URL) by id. Tears down the row plus its associated state (uploaded document for FILE rows, Trust Center references, Oso facts, chunk-store entries) via . Returns 404 when the id is unknown in the calling token's domain. # Get Answer Library entry Source: https://developer.vanta.com/api-reference/knowledge-base/get-answer-library-entry /reference/manage-vanta.json get /knowledge-base/answer-library/{id} Get an Answer Library entry. # Get Knowledge Base resource Source: https://developer.vanta.com/api-reference/knowledge-base/get-knowledge-base-resource /reference/manage-vanta.json get /knowledge-base/resources/{id} Fetch a single Knowledge Base resource (FILE or URL) by id. Returns the same `type`-discriminated union as the list endpoint, so callers can branch on `type` without knowing the kind ahead of time. Returns 404 when the resource does not exist in the domain or — for FILE rows — when the underlying uploaded document has been deleted. # List Answer Library entries Source: https://developer.vanta.com/api-reference/knowledge-base/list-answer-library-entries /reference/manage-vanta.json get /knowledge-base/answer-library List Answer Library entries. Supports full-text search, tag filtering (OR across the given tags), and date-range filters on last-updated and expiration. Entries are returned most-recently-updated first. # List Knowledge Base resources Source: https://developer.vanta.com/api-reference/knowledge-base/list-knowledge-base-resources /reference/manage-vanta.json get /knowledge-base/resources List Knowledge Base resources (documents and webpages) in a single paginated response. Each entry is a discriminated union on `type` — "FILE" entries carry a `fileUrl` (presigned S3 URL, valid for one hour), "URL" entries carry the resource's `url` and `includeSubPages`. Supports full-text search, type filtering, tag filtering (OR within a category, AND across categories), and date-range filters on last-updated and expiration. Resources are returned most-recently-updated first. # Replace document resource file Source: https://developer.vanta.com/api-reference/knowledge-base/replace-document-resource-file /reference/manage-vanta.json post /knowledge-base/resources/documents/{id}/upload Replace the underlying file on a document (FILE-type) resource with a new multipart upload. Other resource fields (title, description, visibility, tags, owner, etc.) are unchanged — use PATCH for those. Returns 404 for an unknown id or a URL-type resource. Example: send `multipart/form-data` with a single `file` field (the new document binary). # Update Answer Library entry Source: https://developer.vanta.com/api-reference/knowledge-base/update-answer-library-entry /reference/manage-vanta.json patch /knowledge-base/answer-library/{id} Update an Answer Library entry. # Update document resource Source: https://developer.vanta.com/api-reference/knowledge-base/update-document-resource /reference/manage-vanta.json patch /knowledge-base/resources/documents/{id} Apply a partial update to a document (FILE-type) resource. Omitted fields are left untouched. To swap the underlying file, use `POST /v1/knowledge-base/resources/documents/{id}/upload`. Returns 404 for an unknown id or a URL-type resource. # Update webpage resource Source: https://developer.vanta.com/api-reference/knowledge-base/update-webpage-resource /reference/manage-vanta.json patch /knowledge-base/resources/webpages/{id} Apply a partial update to a webpage (URL-type) resource. Omitted fields are left untouched. `description`, `ownerAssignment`, and `expirationDate` accept `null` to clear. The resource URL is not updatable here — recreate the resource if the URL needs to change. Returns 404 for an unknown id or a FILE-type resource. # Verify Answer Library entry Source: https://developer.vanta.com/api-reference/knowledge-base/verify-answer-library-entry /reference/manage-vanta.json post /knowledge-base/answer-library/{id}/verify Mark an Answer Library entry as verified. Stamps `lastVerifiedAt` to the current time and uses the supplied expiration date or configured review cadence. The entry's question, answer, tags, and owner are left unchanged. # Verify Knowledge Base resource Source: https://developer.vanta.com/api-reference/knowledge-base/verify-knowledge-base-resource /reference/manage-vanta.json post /knowledge-base/resources/{id}/verify Mark a Knowledge Base resource (FILE or URL) as verified. Stamps `lastVerifiedAt` to the current time and resets `expiresAt` forward by the domain's configured review cadence; the resource's content (title, description, file or url, tags, owner) is left unchanged. Caller does not need to know the resource type — the persisted `resourceType` is used. Returns 404 when the id is unknown in the domain or — for FILE rows — when the underlying uploaded document has been deleted. # List all MacOS User Computers Source: https://developer.vanta.com/api-reference/macos-user-computers/list-all-macos-user-computers /reference/build-integrations.json get /v1/resources/macos_user_computer List `MacosUserComputer` resources for the given application. ** Headers ** ``` Authorization: Bearer ``` ** Scopes ** ``` connectors.self:read-resource ``` # Sync all MacOS User Computers Source: https://developer.vanta.com/api-reference/macos-user-computers/sync-all-macos-user-computers /reference/build-integrations.json put /v1/resources/macos_user_computer To send us data related to employee/contractor MacOS computers, you send us `MacosUserComputer` resources. This helps us determine important security properties, like whether devices have encrypted drives, have anti-virus installed or have password managers installed. This call replaces ALL existing `MacosUserComputer` resources for the given app and `source_id` - this is a "state of the world" sync. In other words, if a `MacosUserComputer` resource is sent for a user in a previous `sync_all` call, but is not included in a later `sync_all` call for that customer, it is assumed to no longer exist and is deleted in Vanta. ** Headers ** ``` Authorization: Bearer ``` ** Scopes ** ``` connectors.self:write-resource ``` ** Schema ** Expand the `resources` array below for the schema of `MacosUserComputer`. # Get monitored computer by ID Source: https://developer.vanta.com/api-reference/monitored-computers/get-monitored-computer-by-id /reference/manage-vanta.json get /monitored-computers/{computerId} Returns a monitored computer by ID. # List monitored computers Source: https://developer.vanta.com/api-reference/monitored-computers/list-monitored-computers /reference/manage-vanta.json get /monitored-computers Returns a list of computers monitored by an MDM (with an integration built by Vanta) or by Vanta Device Monitor. Currently this list does not include resources from partner or customer-built integrations. # List all Package Vulnerabilities Source: https://developer.vanta.com/api-reference/package-vulnerabilities/list-all-package-vulnerabilities /reference/build-integrations.json get /v1/resources/package_vulnerability_connectors List `PackageVulnerabilityConnectors` resources for the given application. ** Headers ** ``` Authorization: Bearer ``` ** Scopes ** ``` connectors.self:read-resource ``` # Sync all Package Vulnerabilities Source: https://developer.vanta.com/api-reference/package-vulnerabilities/sync-all-package-vulnerabilities /reference/build-integrations.json put /v1/resources/package_vulnerability_connectors To send us data related to package vulnerabilities. Note that you must first sync `VulnerableComponent` resources before sending us this data, and this sync should reference the `uniqueId` field in the `VulnerableComponent` resource. This call replaces ALL existing `PackageVulnerabilityConnectors` resources for the given app and `source_id` - this is a "state of the world" sync. In other words, if a `PackageVulnerabilityConnectors` resource is sent for a user in a previous `sync_all` call, but is not included in a later `sync_all` call for that customer, it is assumed to no longer exist and is deleted in Vanta. ** Headers ** ``` Authorization: Bearer ``` ** Scopes ** ``` connectors.self:write-resource ``` ** Schema ** Expand the `resources` array below for the schema of `PackageVulnerabilityConnectors`. # Get person by ID Source: https://developer.vanta.com/api-reference/people/get-person-by-id /reference/manage-vanta.json get /people/{personId} Returns a person by ID. # List people Source: https://developer.vanta.com/api-reference/people/list-people /reference/manage-vanta.json get /people Returns a list of all people. # Mark as not people Source: https://developer.vanta.com/api-reference/people/mark-as-not-people /reference/manage-vanta.json post /people/mark-as-not-people Mark a set of accounts on the People Page as "not a person." As a result, these accounts will not be treated as people in Vanta, and you will not be able to assign them tasks or use them in tests related to your company's personnel. # Mark as people Source: https://developer.vanta.com/api-reference/people/mark-as-people /reference/manage-vanta.json post /people/mark-as-people Mark a set of accounts on the People Page as "people." As a result, these accounts will be treated as people in Vanta, and you will be able to assign them tasks and use them in tests related to your company's personnel. # Offboard people Source: https://developer.vanta.com/api-reference/people/offboard-people /reference/manage-vanta.json post /people/offboard Offboard a list of people. A person is only eligible for offboarding completion when: 1. They are an ex-employee. 2. All of the person's monitored accounts are deactivated or manually overwritten as such. 3. All of a person's custom offboarding tasks have been completed. All of the person's unmonitored accounts will be automatically marked as deactivated when they are offboarded. If the person has unfinished offboarding tasks those will NOT automatically be completed and offboarding them will fail. # Remove leave information Source: https://developer.vanta.com/api-reference/people/remove-leave-information /reference/manage-vanta.json post /people/{personId}/clear-leave Remove leave information on a person. The person will become active in Vanta, and will be considered in certain tests related to personnel. # Set leave information Source: https://developer.vanta.com/api-reference/people/set-leave-information /reference/manage-vanta.json post /people/{personId}/set-leave Set leave information on a person. A person on leave is inactive in Vanta and will not be considered in certain personnel-related tests. If the person has existing leave information, it will be cleared and replaced. # Update person metadata Source: https://developer.vanta.com/api-reference/people/update-person-metadata /reference/manage-vanta.json patch /people/{personId} Update a person's basic information. # Get personnel notification settings Source: https://developer.vanta.com/api-reference/personnel-notification-settings/get-personnel-notification-settings /reference/manage-vanta.json get /personnel-notification-settings Returns the organization's personnel reminder and employee-digest settings. # Update personnel notification settings Source: https://developer.vanta.com/api-reference/personnel-notification-settings/update-personnel-notification-settings /reference/manage-vanta.json patch /personnel-notification-settings Partially updates the organization's personnel reminder and employee-digest settings. Omitted fields remain unchanged. # Get policy by ID Source: https://developer.vanta.com/api-reference/policies/get-policy-by-id /reference/manage-vanta.json get /policies/{policyId} Gets a policy by ID. Policy IDs can be found in Vanta in URL bar after /policies/. # List policies Source: https://developer.vanta.com/api-reference/policies/list-policies /reference/manage-vanta.json get /policies Lists all policies. # Get program scope by ID Source: https://developer.vanta.com/api-reference/program-scopes/get-program-scope-by-id /reference/manage-vanta.json get /program-scopes/{programScopeId} Get a program scope by ID. When business unit scoping is disabled, businessUnitId is null. # List program scopes Source: https://developer.vanta.com/api-reference/program-scopes/list-program-scopes /reference/manage-vanta.json get /program-scopes Lists the program scopes for your organization. A program scope pairs a business unit with a framework that business unit is in scope for. When business unit scoping is disabled, businessUnitId is null. # Questionnaire created Source: https://developer.vanta.com/api-reference/questionnaire/questionnaire-created /reference/webhooks.json post /v1.questionnaire.created A questionnaire was created. # Questionnaire deleted Source: https://developer.vanta.com/api-reference/questionnaire/questionnaire-deleted /reference/webhooks.json post /v1.questionnaire.deleted A questionnaire was deleted. # Questionnaire export completed Source: https://developer.vanta.com/api-reference/questionnaire/questionnaire-export-completed /reference/webhooks.json post /v1.questionnaire.export-completed A questionnaire export has completed successfully. # Questionnaire export failed Source: https://developer.vanta.com/api-reference/questionnaire/questionnaire-export-failed /reference/webhooks.json post /v1.questionnaire.export-failed A questionnaire export has failed. # Questionnaire status changed Source: https://developer.vanta.com/api-reference/questionnaire/questionnaire-status-changed /reference/webhooks.json post /v1.questionnaire.status-changed A questionnaire status was changed. # Add a control to a risk scenario Source: https://developer.vanta.com/api-reference/risk-scenarios/add-a-control-to-a-risk-scenario /reference/manage-vanta.json post /risk-scenarios/{riskScenarioId}/controls Associate a control with a risk scenario. Body: `{ controlId, controlType? }`. `controlType` is `TREATMENT_PLAN` for a control that is part of the risk's treatment plan; omit it (or pass `EXISTING`) to associate the control as a plain existing control. `controlId` may be a Vanta control shorthand, custom-control shorthand, or object ID; it resolves to a single canonical control before any write. Behavior on conflict with an existing association: - Same resolved control already associated with the same `controlType`: the request is a no-op and the existing relationship is returned (200). - Same resolved control associated with the other `controlType`: the request is rejected with a hint to use `PATCH` instead (422). # Cancel risk scenario approval request Source: https://developer.vanta.com/api-reference/risk-scenarios/cancel-risk-scenario-approval-request /reference/manage-vanta.json post /risk-scenarios/{riskScenarioId}/cancel-approval-request Cancel approval request for a risk scenario. # Change a risk scenario control's controlType Source: https://developer.vanta.com/api-reference/risk-scenarios/change-a-risk-scenario-controls-controltype /reference/manage-vanta.json patch /risk-scenarios/{riskScenarioId}/controls/{controlId} Change the `controlType` on an existing risk-scenario / control association. Body: `{ controlType }`. The server atomically moves the resolved control between the treatment-plan and existing-control sets in a single update — there is no intermediate unlinked state. `PATCH { "controlType": "EXISTING" }` removes the control from the treatment plan but keeps it linked as an existing control; use `DELETE` to unlink it entirely. Returns 404 if the control is not currently associated with the scenario. Setting the `controlType` it already has is a 200 no-op. # Create risk scenario Source: https://developer.vanta.com/api-reference/risk-scenarios/create-risk-scenario /reference/manage-vanta.json post /risk-scenarios Create a new risk scenario. # Get risk scenario by ID Source: https://developer.vanta.com/api-reference/risk-scenarios/get-risk-scenario-by-id /reference/manage-vanta.json get /risk-scenarios/{riskScenarioId} Get a risk scenario by ID (can be the Risk ID or the object ID). # List risk scenario controls Source: https://developer.vanta.com/api-reference/risk-scenarios/list-risk-scenario-controls /reference/manage-vanta.json get /risk-scenarios/{riskScenarioId}/controls List the controls associated with a risk scenario. Each item is a `{ controlId, controlType }` relationship. `controlType` is `TREATMENT_PLAN` for controls that are part of the risk's treatment plan, and `EXISTING` for controls linked without a treatment-plan designation. # List risk scenarios Source: https://developer.vanta.com/api-reference/risk-scenarios/list-risk-scenarios /reference/manage-vanta.json get /risk-scenarios List risk scenarios. # Remove a control from a risk scenario Source: https://developer.vanta.com/api-reference/risk-scenarios/remove-a-control-from-a-risk-scenario /reference/manage-vanta.json delete /risk-scenarios/{riskScenarioId}/controls/{controlId} Remove a control from a risk scenario. Fully unlinks the control regardless of whether it is currently a `TREATMENT_PLAN` or an `EXISTING` control. To only drop the treatment-plan designation while keeping the control linked, use `PATCH { "controlType": "EXISTING" }` instead. Deleting an already-unlinked control is an idempotent no-op (204). # Submit risk scenario for approval Source: https://developer.vanta.com/api-reference/risk-scenarios/submit-risk-scenario-for-approval /reference/manage-vanta.json post /risk-scenarios/{riskScenarioId}/submit-for-approval Submit a risk scenario for approval. # Update risk scenario Source: https://developer.vanta.com/api-reference/risk-scenarios/update-risk-scenario /reference/manage-vanta.json patch /risk-scenarios/{riskScenarioId} Update a risk scenario. # List all secrets Source: https://developer.vanta.com/api-reference/secrets/list-all-secrets /reference/build-integrations.json get /v1/resources/secret List `Secret` resources for the given application. ** Headers ** ``` Authorization: Bearer ``` ** Scopes ** ``` connectors.self:read-resource ``` # Sync all secrets Source: https://developer.vanta.com/api-reference/secrets/sync-all-secrets /reference/build-integrations.json put /v1/resources/secret To send metadata of a secret used to access applications or infrastructure, use `Secret`. This call replaces ALL existing `Secret` resources for the given app and `source_id` - this is a "state of the world" sync. In other words, if a `Secret` resource is sent for a user in a previous `sync_all` call, but is not included in a later `sync_all` call for that customer, it is assumed to no longer exist and is deleted in Vanta. ** Headers ** ``` Authorization: Bearer ``` ** Scopes ** ``` connectors.self:write-resource ``` ** Schema ** Expand the `resources` array below for the schema of `Secret`. # List all security tasks Source: https://developer.vanta.com/api-reference/security-tasks/list-all-security-tasks /reference/build-integrations.json get /v1/resources/security_task List `SecurityTask` resources for the given application. ** Headers ** ``` Authorization: Bearer ``` ** Scopes ** ``` connectors.self:read-resource ``` # Sync all security tasks Source: https://developer.vanta.com/api-reference/security-tasks/sync-all-security-tasks /reference/build-integrations.json put /v1/resources/security_task To send us data related to security relevant tasks/follow-ups your system, you send us `SecurityTask` resources. This helps us determine whether security relevant tasks are being completed in a timely manner. This call replaces ALL existing `SecurityTask` resources for the given app and `source_id` - this is a "state of the world" sync. In other words, if a `SecurityTask` resource is sent for a user in a previous `sync_all` call, but is not included in a later `sync_all` call for that customer, it is assumed to no longer exist and is deleted in Vanta. ** Headers ** ``` Authorization: Bearer ``` ** Scopes ** ``` connectors.self:write-resource ``` ** Schema ** Expand the `resources` array below for the schema of `SecurityTask`. # List all Static Code Analysis Vulnerabilities Source: https://developer.vanta.com/api-reference/static-code-analysis-vulnerabilities/list-all-static-code-analysis-vulnerabilities /reference/build-integrations.json get /v1/resources/static_analysis_code_vulnerability_connectors List `StaticAnalysisCodeVulnerabilityConnectors` resources for the given application. ** Headers ** ``` Authorization: Bearer ``` ** Scopes ** ``` connectors.self:read-resource ``` # Sync all Static Code Analysis Vulnerabilities Source: https://developer.vanta.com/api-reference/static-code-analysis-vulnerabilities/sync-all-static-code-analysis-vulnerabilities /reference/build-integrations.json put /v1/resources/static_analysis_code_vulnerability_connectors To send us data related to static code analysis vulnerabilities. Note that you must first sync `VulnerableComponent` resources before sending us this data, and this sync should reference the `uniqueId` field in the `VulnerableComponent` resource. This call replaces ALL existing `StaticAnalysisCodeVulnerabilityConnectors` resources for the given app and `source_id` - this is a "state of the world" sync. In other words, if a `StaticAnalysisCodeVulnerabilityConnectors` resource is sent for a user in a previous `sync_all` call, but is not included in a later `sync_all` call for that customer, it is assumed to no longer exist and is deleted in Vanta. ** Headers ** ``` Authorization: Bearer ``` ** Scopes ** ``` connectors.self:write-resource ``` ** Schema ** Expand the `resources` array below for the schema of `StaticAnalysisCodeVulnerabilityConnectors`. # Deactivate test entity Source: https://developer.vanta.com/api-reference/tests/deactivate-test-entity /reference/manage-vanta.json post /tests/{testId}/entities/{entityId}/deactivate Deactivates a single test item (test entity). There may be a delay in the deactivation of the test entity until the next test run. Use the /vulnerabilities/deactivate endpoint for vulnerabilities. # Get test by ID Source: https://developer.vanta.com/api-reference/tests/get-test-by-id /reference/manage-vanta.json get /tests/{testId} Gets a test by ID. Test IDs can be found in Vanta in URL bar after /tests/. # Get test entities by test ID Source: https://developer.vanta.com/api-reference/tests/get-test-entities-by-test-id /reference/manage-vanta.json get /tests/{testId}/entities Gets a list of tested items (entities) for a test by test ID. An entity is a tested item that can have its own outcome. For example, for a test that makes sure that all S3 buckets are versioned, an individual S3 bucket would be an entity. # List tests Source: https://developer.vanta.com/api-reference/tests/list-tests /reference/manage-vanta.json get /tests Lists all tests based on applied filters. # Reactivate test entity Source: https://developer.vanta.com/api-reference/tests/reactivate-test-entity /reference/manage-vanta.json post /tests/{testId}/entities/{entityId}/reactivate Reactivates a single tested item (test entity). There may be a delay in the reactivation of the test entity until the next test run. Use the /vulnerabilities/reactivate endpoint for vulnerabilities. # Trust Center access request approved Source: https://developer.vanta.com/api-reference/trust-center/trust-center-access-request-approved /reference/webhooks.json post /v1.trust-center.access-request.approved A Trust Center access request was approved. # Trust Center access request denied Source: https://developer.vanta.com/api-reference/trust-center/trust-center-access-request-denied /reference/webhooks.json post /v1.trust-center.access-request.denied A Trust Center access request was denied. # Trust Center access request received Source: https://developer.vanta.com/api-reference/trust-center/trust-center-access-request-received /reference/webhooks.json post /v1.trust-center.access-request.received A Trust Center access request was received. # Add Trust Center control Source: https://developer.vanta.com/api-reference/trust-centers/add-trust-center-control /reference/manage-vanta.json post /trust-centers/{slugId}/controls Adds a control to a Trust Center. # Add Trust Center control category Source: https://developer.vanta.com/api-reference/trust-centers/add-trust-center-control-category /reference/manage-vanta.json post /trust-centers/{slugId}/control-categories Adds a control category to a Trust Center. # Add Trust Center FAQ category Source: https://developer.vanta.com/api-reference/trust-centers/add-trust-center-faq-category /reference/manage-vanta.json post /trust-centers/{slugId}/faq-categories Adds an FAQ category to a Trust Center. # Add Trust Center resource category Source: https://developer.vanta.com/api-reference/trust-centers/add-trust-center-resource-category /reference/manage-vanta.json post /trust-centers/{slugId}/resource-categories Adds a resource category to a Trust Center. # Add Trust Center viewer Source: https://developer.vanta.com/api-reference/trust-centers/add-trust-center-viewer /reference/manage-vanta.json post /trust-centers/{slugId}/viewers Adds a viewer and grants them access to a Trust Center. # Approve Trust Center access request Source: https://developer.vanta.com/api-reference/trust-centers/approve-trust-center-access-request /reference/manage-vanta.json post /trust-centers/{slugId}/access-requests/{accessRequestId}/approve Approves an access request on a Trust Center. # Bulk add tags to Trust Center controls Source: https://developer.vanta.com/api-reference/trust-centers/bulk-add-tags-to-trust-center-controls /reference/manage-vanta.json post /trust-centers/{slugId}/controls/tags Adds tags to multiple controls on a Trust Center. Limited to 100 controls per request. # Bulk edit controls in a category Source: https://developer.vanta.com/api-reference/trust-centers/bulk-edit-controls-in-a-category /reference/manage-vanta.json patch /trust-centers/{slugId}/control-categories/{categoryId}/controls Bulk add or remove controls from a control category on a Trust Center. # Bulk remove tags from Trust Center controls Source: https://developer.vanta.com/api-reference/trust-centers/bulk-remove-tags-from-trust-center-controls /reference/manage-vanta.json delete /trust-centers/{slugId}/controls/tags Removes tags from multiple controls on a Trust Center. Limited to 100 controls per request. # Create Trust Center compliance framework Source: https://developer.vanta.com/api-reference/trust-centers/create-trust-center-compliance-framework /reference/manage-vanta.json post /trust-centers/{slugId}/compliance-frameworks Adds a compliance framework to a Trust Center. # Create Trust Center document Source: https://developer.vanta.com/api-reference/trust-centers/create-trust-center-document /reference/manage-vanta.json post /trust-centers/{slugId}/resources Adds a document to a Trust Center. # Create Trust Center FAQ Source: https://developer.vanta.com/api-reference/trust-centers/create-trust-center-faq /reference/manage-vanta.json post /trust-centers/{slugId}/faqs Adds an FAQ to a Trust Center. # Create Trust Center subprocessor Source: https://developer.vanta.com/api-reference/trust-centers/create-trust-center-subprocessor /reference/manage-vanta.json post /trust-centers/{slugId}/subprocessors Adds a subprocessor to a Trust Center. # Create Trust Center subscriber Source: https://developer.vanta.com/api-reference/trust-centers/create-trust-center-subscriber /reference/manage-vanta.json post /trust-centers/{slugId}/subscribers Adds a subscriber to a Trust Center. # Create Trust Center subscriber group Source: https://developer.vanta.com/api-reference/trust-centers/create-trust-center-subscriber-group /reference/manage-vanta.json post /trust-centers/{slugId}/subscriber-groups Adds a subscriber group to a Trust Center. # Create Trust Center update Source: https://developer.vanta.com/api-reference/trust-centers/create-trust-center-update /reference/manage-vanta.json post /trust-centers/{slugId}/updates Adds an update to a Trust Center. # Delete Trust Center compliance framework Source: https://developer.vanta.com/api-reference/trust-centers/delete-trust-center-compliance-framework /reference/manage-vanta.json delete /trust-centers/{slugId}/compliance-frameworks/{frameworkId} Removes a compliance framework from a Trust Center. # Delete Trust Center control Source: https://developer.vanta.com/api-reference/trust-centers/delete-trust-center-control /reference/manage-vanta.json delete /trust-centers/{slugId}/controls/{controlId} Removes a specific control from a Trust Center. This removes the control from all of the control categories that is in. # Delete Trust Center control category Source: https://developer.vanta.com/api-reference/trust-centers/delete-trust-center-control-category /reference/manage-vanta.json delete /trust-centers/{slugId}/control-categories/{categoryId} Removes a control category from a Trust Center along with all of the controls in the category. # Delete Trust Center document Source: https://developer.vanta.com/api-reference/trust-centers/delete-trust-center-document /reference/manage-vanta.json delete /trust-centers/{slugId}/resources/{resourceId} Removes a specific document from a Trust Center. # Delete Trust Center FAQ Source: https://developer.vanta.com/api-reference/trust-centers/delete-trust-center-faq /reference/manage-vanta.json delete /trust-centers/{slugId}/faqs/{faqId} Remove a specific FAQ from the Trust Center by ID. # Delete Trust Center FAQ category Source: https://developer.vanta.com/api-reference/trust-centers/delete-trust-center-faq-category /reference/manage-vanta.json delete /trust-centers/{slugId}/faq-categories/{categoryId} Removes an FAQ category from a Trust Center. FAQs in the deleted category are moved to uncategorized. # Delete Trust Center resource category Source: https://developer.vanta.com/api-reference/trust-centers/delete-trust-center-resource-category /reference/manage-vanta.json delete /trust-centers/{slugId}/resource-categories/{categoryId} Removes a resource category from a Trust Center. Resources in the deleted category are moved to uncategorized. # Delete Trust Center subprocessor Source: https://developer.vanta.com/api-reference/trust-centers/delete-trust-center-subprocessor /reference/manage-vanta.json delete /trust-centers/{slugId}/subprocessors/{subprocessorId} Removes a subprocessor from a Trust Center. # Delete Trust Center subscriber Source: https://developer.vanta.com/api-reference/trust-centers/delete-trust-center-subscriber /reference/manage-vanta.json delete /trust-centers/{slugId}/subscribers/{subscriberId} Removes a subscriber from a Trust Center. # Delete Trust Center subscriber group Source: https://developer.vanta.com/api-reference/trust-centers/delete-trust-center-subscriber-group /reference/manage-vanta.json delete /trust-centers/{slugId}/subscriber-groups/{subscriberGroupId} Removes a subscriber group from a Trust Center. # Delete Trust Center update Source: https://developer.vanta.com/api-reference/trust-centers/delete-trust-center-update /reference/manage-vanta.json delete /trust-centers/{slugId}/updates/{updateId} Removes an update from a Trust Center. # Deny Trust Center access request Source: https://developer.vanta.com/api-reference/trust-centers/deny-trust-center-access-request /reference/manage-vanta.json post /trust-centers/{slugId}/access-requests/{accessRequestId}/deny Denies an access request on a Trust Center. The requester is only notified by email when `sendEmail` is true. # Edit Trust Center subscriber group Source: https://developer.vanta.com/api-reference/trust-centers/edit-trust-center-subscriber-group /reference/manage-vanta.json patch /trust-centers/{slugId}/subscriber-groups/{subscriberGroupId} Edits a Trust Center subscriber group. # Get Trust Center Source: https://developer.vanta.com/api-reference/trust-centers/get-trust-center /reference/manage-vanta.json get /trust-centers/{slugId} Gets a Trust Center by slug ID. # Get Trust Center access request Source: https://developer.vanta.com/api-reference/trust-centers/get-trust-center-access-request /reference/manage-vanta.json get /trust-centers/{slugId}/access-requests/{accessRequestId} Gets a specific access request for a Trust Center. # Get Trust Center chatbot conversation messages Source: https://developer.vanta.com/api-reference/trust-centers/get-trust-center-chatbot-conversation-messages /reference/manage-vanta.json get /trust-centers/{slugId}/chatbot/conversations/{conversationId} Gets the messages for a specific chatbot conversation on a Trust Center. # Get Trust Center control Source: https://developer.vanta.com/api-reference/trust-centers/get-trust-center-control /reference/manage-vanta.json get /trust-centers/{slugId}/controls/{controlId} Gets a specific control on a Trust Center. # Get Trust Center control category Source: https://developer.vanta.com/api-reference/trust-centers/get-trust-center-control-category /reference/manage-vanta.json get /trust-centers/{slugId}/control-categories/{categoryId} Gets a specific control category on a Trust Center. # Get Trust Center document Source: https://developer.vanta.com/api-reference/trust-centers/get-trust-center-document /reference/manage-vanta.json get /trust-centers/{slugId}/resources/{resourceId} Gets a specific document on a Trust Center. # Get Trust Center FAQ Source: https://developer.vanta.com/api-reference/trust-centers/get-trust-center-faq /reference/manage-vanta.json get /trust-centers/{slugId}/faqs/{faqId} Gets a specific FAQ on the Trust Center by ID. # Get Trust Center subprocessor Source: https://developer.vanta.com/api-reference/trust-centers/get-trust-center-subprocessor /reference/manage-vanta.json get /trust-centers/{slugId}/subprocessors/{subprocessorId} Gets a specific subprocessor on a Trust Center. # Get Trust Center subscriber Source: https://developer.vanta.com/api-reference/trust-centers/get-trust-center-subscriber /reference/manage-vanta.json get /trust-centers/{slugId}/subscribers/{subscriberId} Gets a specific subscriber on a Trust Center. # Get Trust Center subscriber group Source: https://developer.vanta.com/api-reference/trust-centers/get-trust-center-subscriber-group /reference/manage-vanta.json get /trust-centers/{slugId}/subscriber-groups/{subscriberGroupId} Get a subscriber group by ID. # Get Trust Center update Source: https://developer.vanta.com/api-reference/trust-centers/get-trust-center-update /reference/manage-vanta.json get /trust-centers/{slugId}/updates/{updateId} Gets a specific update on a Trust Center. # Get Trust Center viewer Source: https://developer.vanta.com/api-reference/trust-centers/get-trust-center-viewer /reference/manage-vanta.json get /trust-centers/{slugId}/viewers/{viewerId} Gets a specific viewer for a Trust Center. # Get uploaded media for Trust Center document Source: https://developer.vanta.com/api-reference/trust-centers/get-uploaded-media-for-trust-center-document /reference/manage-vanta.json get /trust-centers/{slugId}/resources/{resourceId}/media Gets the actual given uploaded document for a Trust Center. # List historical Trust Center access requests Source: https://developer.vanta.com/api-reference/trust-centers/list-historical-trust-center-access-requests /reference/manage-vanta.json get /trust-centers/{slugId}/historical-access-requests Gets a list of historical (approved or denied) access requests for a Trust Center. # List Trust Center access requests Source: https://developer.vanta.com/api-reference/trust-centers/list-trust-center-access-requests /reference/manage-vanta.json get /trust-centers/{slugId}/access-requests Gets a list of access requests for a Trust Center. # List Trust Center chatbot conversations Source: https://developer.vanta.com/api-reference/trust-centers/list-trust-center-chatbot-conversations /reference/manage-vanta.json get /trust-centers/{slugId}/chatbot/conversations Gets a paginated list of chatbot conversations on a Trust Center. # List Trust Center compliance frameworks Source: https://developer.vanta.com/api-reference/trust-centers/list-trust-center-compliance-frameworks /reference/manage-vanta.json get /trust-centers/{slugId}/compliance-frameworks Gets the list of compliance frameworks on a Trust Center. # List Trust Center control categories Source: https://developer.vanta.com/api-reference/trust-centers/list-trust-center-control-categories /reference/manage-vanta.json get /trust-centers/{slugId}/control-categories Gets a list of control categories on a Trust Center. # List Trust Center controls Source: https://developer.vanta.com/api-reference/trust-centers/list-trust-center-controls /reference/manage-vanta.json get /trust-centers/{slugId}/controls Gets a list of controls on a Trust Center. # List Trust Center data collected Source: https://developer.vanta.com/api-reference/trust-centers/list-trust-center-data-collected /reference/manage-vanta.json get /trust-centers/{slugId}/data-collected Gets the list of data-collected disclosures on a Trust Center. # List Trust Center FAQ categories Source: https://developer.vanta.com/api-reference/trust-centers/list-trust-center-faq-categories /reference/manage-vanta.json get /trust-centers/{slugId}/faq-categories Gets a list of FAQ categories on a Trust Center. # List Trust Center FAQs Source: https://developer.vanta.com/api-reference/trust-centers/list-trust-center-faqs /reference/manage-vanta.json get /trust-centers/{slugId}/faqs Gets a list of FAQs on a Trust Center. # List Trust Center resource categories Source: https://developer.vanta.com/api-reference/trust-centers/list-trust-center-resource-categories /reference/manage-vanta.json get /trust-centers/{slugId}/resource-categories Gets a list of resource categories on a Trust Center. # List Trust Center resources Source: https://developer.vanta.com/api-reference/trust-centers/list-trust-center-resources /reference/manage-vanta.json get /trust-centers/{slugId}/resources Gets a list of resources on a Trust Center. # List Trust Center subprocessors Source: https://developer.vanta.com/api-reference/trust-centers/list-trust-center-subprocessors /reference/manage-vanta.json get /trust-centers/{slugId}/subprocessors Gets the list of subprocessors on a Trust Center. # List Trust Center subscriber groups Source: https://developer.vanta.com/api-reference/trust-centers/list-trust-center-subscriber-groups /reference/manage-vanta.json get /trust-centers/{slugId}/subscriber-groups Gets a list of subscriber groups on a Trust Center. # List Trust Center subscribers Source: https://developer.vanta.com/api-reference/trust-centers/list-trust-center-subscribers /reference/manage-vanta.json get /trust-centers/{slugId}/subscribers Gets a list of subscribers on a Trust Center. # List Trust Center updates Source: https://developer.vanta.com/api-reference/trust-centers/list-trust-center-updates /reference/manage-vanta.json get /trust-centers/{slugId}/updates Gets a list of updates on a Trust Center. # List Trust Center viewer activity events Source: https://developer.vanta.com/api-reference/trust-centers/list-trust-center-viewer-activity-events /reference/manage-vanta.json get /trust-centers/{slugId}/activity Gets a list of viewer activity events on a Trust Center. # List Trust Center viewers Source: https://developer.vanta.com/api-reference/trust-centers/list-trust-center-viewers /reference/manage-vanta.json get /trust-centers/{slugId}/viewers Gets a list of viewers that have been granted access to a Trust Center. # Remove Trust Center viewer Source: https://developer.vanta.com/api-reference/trust-centers/remove-trust-center-viewer /reference/manage-vanta.json delete /trust-centers/{slugId}/viewers/{viewerId} Revokes a viewer's access to a Trust Center. # Reorder controls in a Trust Center control category Source: https://developer.vanta.com/api-reference/trust-centers/reorder-controls-in-a-trust-center-control-category /reference/manage-vanta.json put /trust-centers/{slugId}/control-categories/{categoryId}/controls/order Reorders controls within a control category on a Trust Center. The request body must contain the complete set of control IDs in the category in the desired order. # Reorder Trust Center control categories Source: https://developer.vanta.com/api-reference/trust-centers/reorder-trust-center-control-categories /reference/manage-vanta.json put /trust-centers/{slugId}/control-categories/order Reorders control categories on a Trust Center. The request body must contain the complete set of category IDs in the desired order. # Reorder Trust Center resource categories Source: https://developer.vanta.com/api-reference/trust-centers/reorder-trust-center-resource-categories /reference/manage-vanta.json put /trust-centers/{slugId}/resource-categories/order Reorders resource categories on a Trust Center. The request body must contain the complete set of category IDs in the desired order. # Send Trust Center update notifications to all subscribers Source: https://developer.vanta.com/api-reference/trust-centers/send-trust-center-update-notifications-to-all-subscribers /reference/manage-vanta.json post /trust-centers/{slugId}/updates/{updateId}/notify-all-subscribers Sends notifications for a specific Trust Center update to all subscribers. # Send Trust Center update notifications to specific subscribers Source: https://developer.vanta.com/api-reference/trust-centers/send-trust-center-update-notifications-to-specific-subscribers /reference/manage-vanta.json post /trust-centers/{slugId}/updates/{updateId}/notify-specific-subscribers Sends notifications for a specific Trust Center update to specific subscribers. At least one subscriber group or email address is required. The total number of resolved, deduplicated recipient emails must not exceed 5,000. If exceeded, a 422 error is returned. Narrow your filters or split across multiple requests. # Send Trust Center viewer invite reminder Source: https://developer.vanta.com/api-reference/trust-centers/send-trust-center-viewer-invite-reminder /reference/manage-vanta.json post /trust-centers/{slugId}/viewers/{viewerId}/send-invite-reminder Resends the invite email for a Trust Center viewer. # Set groups for a Trust Center subscriber Source: https://developer.vanta.com/api-reference/trust-centers/set-groups-for-a-trust-center-subscriber /reference/manage-vanta.json put /trust-centers/{slugId}/subscribers/{subscriberId}/groups Sets groups on a subscriber. # Set Trust Center data collected Source: https://developer.vanta.com/api-reference/trust-centers/set-trust-center-data-collected /reference/manage-vanta.json put /trust-centers/{slugId}/data-collected Replaces all data-collected disclosures on a Trust Center with the provided list. This is a full replacement — any existing disclosures not included in the request body will be removed. To add or remove a single entry, first GET the current list, modify it, then PUT the updated list back. # Set Trust Center videos Source: https://developer.vanta.com/api-reference/trust-centers/set-trust-center-videos /reference/manage-vanta.json put /trust-centers/{slugId}/videos Configures the videos displayed on a Trust Center. Replaces all existing videos with the provided list. # Update Trust Center Source: https://developer.vanta.com/api-reference/trust-centers/update-trust-center /reference/manage-vanta.json patch /trust-centers/{slugId} Updates a Trust Center by slug ID. # Update Trust Center compliance framework Source: https://developer.vanta.com/api-reference/trust-centers/update-trust-center-compliance-framework /reference/manage-vanta.json patch /trust-centers/{slugId}/compliance-frameworks/{frameworkId} Updates a compliance framework on a Trust Center. # Update Trust Center control category Source: https://developer.vanta.com/api-reference/trust-centers/update-trust-center-control-category /reference/manage-vanta.json patch /trust-centers/{slugId}/control-categories/{categoryId} Updates a control category on a Trust Center. # Update Trust Center document Source: https://developer.vanta.com/api-reference/trust-centers/update-trust-center-document /reference/manage-vanta.json patch /trust-centers/{slugId}/resources/{resourceId} Updates a specific document on a Trust Center. # Update Trust Center FAQ Source: https://developer.vanta.com/api-reference/trust-centers/update-trust-center-faq /reference/manage-vanta.json patch /trust-centers/{slugId}/faqs/{faqId} Update a specific FAQ on the Trust Center by ID. # Update Trust Center FAQ category Source: https://developer.vanta.com/api-reference/trust-centers/update-trust-center-faq-category /reference/manage-vanta.json patch /trust-centers/{slugId}/faq-categories/{categoryId} Updates an FAQ category on a Trust Center. # Update Trust Center resource category Source: https://developer.vanta.com/api-reference/trust-centers/update-trust-center-resource-category /reference/manage-vanta.json patch /trust-centers/{slugId}/resource-categories/{categoryId} Updates a resource category on a Trust Center. # Update Trust Center subprocessor Source: https://developer.vanta.com/api-reference/trust-centers/update-trust-center-subprocessor /reference/manage-vanta.json patch /trust-centers/{slugId}/subprocessors/{subprocessorId} Updates a subprocessor on a Trust Center. # Update Trust Center update Source: https://developer.vanta.com/api-reference/trust-centers/update-trust-center-update /reference/manage-vanta.json patch /trust-centers/{slugId}/updates/{updateId} Updates an update on a Trust Center. # Update Trust Center viewer Source: https://developer.vanta.com/api-reference/trust-centers/update-trust-center-viewer /reference/manage-vanta.json patch /trust-centers/{slugId}/viewers/{viewerId} Updates a viewer's access on a Trust Center. # Upload Trust Center compliance framework badge Source: https://developer.vanta.com/api-reference/trust-centers/upload-trust-center-compliance-framework-badge /reference/manage-vanta.json post /trust-centers/{slugId}/compliance-frameworks/{frameworkId}/badge Uploads a badge image for a compliance framework on a Trust Center. # Upload Trust Center favicon Source: https://developer.vanta.com/api-reference/trust-centers/upload-trust-center-favicon /reference/manage-vanta.json post /trust-centers/{slugId}/favicon Uploads a favicon for a Trust Center. The Trust Center must have a custom domain configured. # List all user accounts Source: https://developer.vanta.com/api-reference/user-accounts/list-all-user-accounts /reference/build-integrations.json get /v1/resources/user_account List `UserAccount` resources for the given application. ** Headers ** ``` Authorization: Bearer ``` ** Scopes ** ``` connectors.self:read-resource ``` # Sync all user accounts Source: https://developer.vanta.com/api-reference/user-accounts/sync-all-user-accounts /reference/build-integrations.json put /v1/resources/user_account To send us data related to users in your system, you send us `UserAccount` resources. Every partner must send us `UserAccount` resources. This helps us determine whether users have appropriate levels of access and have a secure authentication mechanism. This call replaces ALL existing `UserAccount` resources for the given app and `source_id` - this is a "state of the world" sync. In other words, if a `UserAccount` resource is sent for a user in a previous `sync_all` call, but is not included in a later `sync_all` call for that customer, it is assumed to no longer exist and it is "deletedAt" time in is set to that of the `sync_all` call. The resource will still show in the Vanta UI as a Deactivated `UserAccount`, and `list_all` calls. ** Headers ** ``` Authorization: Bearer ``` ** Scopes ** ``` connectors.self:write-resource ``` ** Schema ** Expand the `resources` array below for the schema of `UserAccount`. # List all user security training statuses Source: https://developer.vanta.com/api-reference/user-security-training-statuses/list-all-user-security-training-statuses /reference/build-integrations.json get /v1/resources/user_security_training_status List `UserSecurityTrainingStatus` resources for the given application. ** Headers ** ``` Authorization: Bearer ``` ** Scopes ** ``` connectors.self:read-resource ``` # Sync all user security training statuses Source: https://developer.vanta.com/api-reference/user-security-training-statuses/sync-all-user-security-training-statuses /reference/build-integrations.json put /v1/resources/user_security_training_status To send us data related to security trainings, you send us `UserSecurityTrainingStatus` resources. This helps us determine whether users have completed their security and compliance trainings in a timely manner. This call replaces ALL existing `UserSecurityTrainingStatus` resources for the given app and `source_id` - this is a "state of the world" sync. In other words, if a `UserSecurityTrainingStatus` resource is sent for a user in a previous `sync_all` call, but is not included in a later `sync_all` call for that customer, it is assumed to no longer exist and is deleted in Vanta. ** Headers ** ``` Authorization: Bearer ``` ** Scopes ** ``` connectors.self:write-resource ``` ** Schema ** Expand the `resources` array below for the schema of `UserSecurityTrainingStatus`. # Get user by ID Source: https://developer.vanta.com/api-reference/users/get-user-by-id /reference/manage-vanta.json get /users/{userId} Returns a user by ID. # List active users Source: https://developer.vanta.com/api-reference/users/list-active-users /reference/manage-vanta.json get /users Returns a list of all active users. # Get assessment type by ID Source: https://developer.vanta.com/api-reference/vendor-assessment-types/get-assessment-type-by-id /reference/manage-vanta.json get /vendor-assessment-types/{assessmentTypeId} Gets an assessment type by ID. # List assessment types Source: https://developer.vanta.com/api-reference/vendor-assessment-types/list-assessment-types /reference/manage-vanta.json get /vendor-assessment-types Lists the domain's assessment types. Returns both active and archived types by default; pass the `status` query parameter to filter server-side. # List vendor risk attributes Source: https://developer.vanta.com/api-reference/vendor-risk-attributes/list-vendor-risk-attributes /reference/manage-vanta.json get /vendor-risk-attributes Returns a list of vendor risk attributes. # Vendor decision created Source: https://developer.vanta.com/api-reference/vendor/vendor-decision-created /reference/webhooks.json post /v1.vendor.decision.created A new vendor decision has been created. # Add a vendor finding Source: https://developer.vanta.com/api-reference/vendors/add-a-vendor-finding /reference/manage-vanta.json post /vendors/{vendorId}/findings Add vendor finding. # Add document to a vendor Source: https://developer.vanta.com/api-reference/vendors/add-document-to-a-vendor /reference/manage-vanta.json post /vendors/{vendorId}/documents Add document to a vendor. # Add document to security review Source: https://developer.vanta.com/api-reference/vendors/add-document-to-security-review /reference/manage-vanta.json post /vendors/{vendorId}/security-reviews/{securityReviewId}/documents Add document to a security review. # Create a vendor Source: https://developer.vanta.com/api-reference/vendors/create-a-vendor /reference/manage-vanta.json post /vendors Add vendor with metadata. # Delete a security review document by ID Source: https://developer.vanta.com/api-reference/vendors/delete-a-security-review-document-by-id /reference/manage-vanta.json delete /vendors/{vendorId}/security-reviews/{securityReviewId}/documents/{documentId} Delete a security review document. # Delete finding by ID Source: https://developer.vanta.com/api-reference/vendors/delete-finding-by-id /reference/manage-vanta.json delete /vendors/{vendorId}/findings/{findingId} Deletes a finding. # Delete vendor by ID Source: https://developer.vanta.com/api-reference/vendors/delete-vendor-by-id /reference/manage-vanta.json delete /vendors/{vendorId} Deletes a vendor. # Get assessment by ID Source: https://developer.vanta.com/api-reference/vendors/get-assessment-by-id /reference/manage-vanta.json get /vendors/{vendorId}/assessments/{assessmentId} Returns a single assessment for a vendor. # Get security review by ID Source: https://developer.vanta.com/api-reference/vendors/get-security-review-by-id /reference/manage-vanta.json get /vendors/{vendorId}/security-reviews/{securityReviewId} Returns a security review. # Get vendor by ID Source: https://developer.vanta.com/api-reference/vendors/get-vendor-by-id /reference/manage-vanta.json get /vendors/{vendorId} Get a vendor. # List assessments by vendor ID Source: https://developer.vanta.com/api-reference/vendors/list-assessments-by-vendor-id /reference/manage-vanta.json get /vendors/{vendorId}/assessments Returns a vendor's assessments across all assessment types. # List security review documents Source: https://developer.vanta.com/api-reference/vendors/list-security-review-documents /reference/manage-vanta.json get /vendors/{vendorId}/security-reviews/{securityReviewId}/documents Lists a security review's documents. # List security reviews by vendor ID Source: https://developer.vanta.com/api-reference/vendors/list-security-reviews-by-vendor-id /reference/manage-vanta.json get /vendors/{vendorId}/security-reviews Returns a vendor's security reviews. # List vendor documents Source: https://developer.vanta.com/api-reference/vendors/list-vendor-documents /reference/manage-vanta.json get /vendors/{vendorId}/documents Returns a vendor's list of documents. # List vendor findings Source: https://developer.vanta.com/api-reference/vendors/list-vendor-findings /reference/manage-vanta.json get /vendors/{vendorId}/findings Lists a vendor's findings. # List vendors Source: https://developer.vanta.com/api-reference/vendors/list-vendors /reference/manage-vanta.json get /vendors List of vendors. # Set vendor status Source: https://developer.vanta.com/api-reference/vendors/set-vendor-status /reference/manage-vanta.json post /vendors/{vendorId}/set-status Sets the status of a vendor, which can be MANAGED, ARCHIVED, or IN_PROCUREMENT. # Update vendor by ID Source: https://developer.vanta.com/api-reference/vendors/update-vendor-by-id /reference/manage-vanta.json patch /vendors/{vendorId} Update vendor. # Update vendor finding Source: https://developer.vanta.com/api-reference/vendors/update-vendor-finding /reference/manage-vanta.json patch /vendors/{vendorId}/findings/{findingId} Update vendor finding. # Deactivate vulnerability monitoring for a vulnerability Source: https://developer.vanta.com/api-reference/vulnerabilities/deactivate-vulnerability-monitoring-for-a-vulnerability /reference/manage-vanta.json post /vulnerabilities/deactivate Deactivate monitoring for select vulnerabilities. Vanta will not monitor a deactivated vulnerability until it is reactivated. # Get vulnerabilities Source: https://developer.vanta.com/api-reference/vulnerabilities/get-vulnerabilities /reference/manage-vanta.json get /vulnerabilities List all vulnerabilities based on selected filters. # Get vulnerability by ID Source: https://developer.vanta.com/api-reference/vulnerabilities/get-vulnerability-by-id /reference/manage-vanta.json get /vulnerabilities/{vulnerabilityId} Gets a vulnerability by an ID. # Reactivate vulnerability monitoring Source: https://developer.vanta.com/api-reference/vulnerabilities/reactivate-vulnerability-monitoring /reference/manage-vanta.json post /vulnerabilities/reactivate Reactivate vulnerabilities and resume Vanta monitoring. # Acknowledge SLA miss Source: https://developer.vanta.com/api-reference/vulnerability-remediations/acknowledge-sla-miss /reference/manage-vanta.json post /vulnerability-remediations/acknowledge-sla-miss Acknowledge an SLA miss for a vulnerability remediation. # List vulnerability remediations Source: https://developer.vanta.com/api-reference/vulnerability-remediations/list-vulnerability-remediations /reference/manage-vanta.json get /vulnerability-remediations List all vulnerability remediations based on selected filters. # Get vulnerable asset by ID Source: https://developer.vanta.com/api-reference/vulnerable-assets/get-vulnerable-asset-by-id /reference/manage-vanta.json get /vulnerable-assets/{vulnerableAssetId} Gets a vulnerable asset by ID. # List assets associated with vulnerabilities Source: https://developer.vanta.com/api-reference/vulnerable-assets/list-assets-associated-with-vulnerabilities /reference/manage-vanta.json get /vulnerable-assets List assets that Vanta monitors that are associated with vulnerabilities. # List all Vulnerable Components Source: https://developer.vanta.com/api-reference/vulnerable-components/list-all-vulnerable-components /reference/build-integrations.json get /v1/resources/vulnerable_component List `VulnerableComponent` resources for the given application. ** Headers ** ``` Authorization: Bearer ``` ** Scopes ** ``` connectors.self:read-resource ``` # Sync all Vulnerable Components Source: https://developer.vanta.com/api-reference/vulnerable-components/sync-all-vulnerable-components /reference/build-integrations.json put /v1/resources/vulnerable_component To send us data related to system components that have vulnerabilities. This call replaces ALL existing `VulnerableComponent` resources for the given app and `source_id` - this is a "state of the world" sync. In other words, if a `VulnerableComponent` resource is sent for a user in a previous `sync_all` call, but is not included in a later `sync_all` call for that customer, it is assumed to no longer exist and is deleted in Vanta. ** Headers ** ``` Authorization: Bearer ``` ** Scopes ** ``` connectors.self:write-resource ``` ** Schema ** Expand the `resources` array below for the schema of `VulnerableComponent`. # List all Windows User Computers Source: https://developer.vanta.com/api-reference/windows-user-computers/list-all-windows-user-computers /reference/build-integrations.json get /v1/resources/windows_user_computer List `WindowsUserComputer` resources for the given application. ** Headers ** ``` Authorization: Bearer ``` ** Scopes ** ``` connectors.self:read-resource ``` # Sync all Windows User Computers Source: https://developer.vanta.com/api-reference/windows-user-computers/sync-all-windows-user-computers /reference/build-integrations.json put /v1/resources/windows_user_computer To send us data related to employee/contractor Windows computers, you send us `WindowsUserComputer` resources. This helps us determine important security properties, like whether devices have encrypted drives, have anti-virus installed or have password managers installed. This call replaces ALL existing `WindowsUserComputer` resources for the given app and `source_id` - this is a "state of the world" sync. In other words, if a `WindowsUserComputer` resource is sent for a user in a previous `sync_all` call, but is not included in a later `sync_all` call for that customer, it is assumed to no longer exist and is deleted in Vanta. ** Headers ** ``` Authorization: Bearer ``` ** Scopes ** ``` connectors.self:write-resource ``` ** Schema ** Expand the `resources` array below for the schema of `WindowsUserComputer`. # Install Vanta AI Skills Source: https://developer.vanta.com/docs/ai-skills Vanta publishes agentskills.io-spec skill files that give your AI coding tool Vanta-specific guidance. Install them with one command or add the Vanta Developer Docs MCP server. Vanta publishes skill files that give your AI coding tool everything it needs to build well-formed integrations. They cover the edge cases, quirks, and rules that trip up humans and agents alike. ## Install Vanta's skills are available two ways: as MCP resources via the [developer docs MCP server](https://developer.vanta.com/mcp), or as local files installed by the [skills CLI](https://www.npmjs.com/package/skills). The MCP server at `https://developer.vanta.com/mcp` exposes search over the developer docs and serves every page as a `skill.md` resource. It is separate from the [Vanta product MCP server](/docs/vanta-mcp) at `https://mcp.vanta.com/mcp`, which lets your agent act on a Vanta tenant. Install MCP Server in Cursor Add to VS Code ```bash theme={"system"} claude mcp add --transport http vanta-docs https://developer.vanta.com/mcp ``` Verify with `claude mcp list`, then run `/mcp` inside Claude Code, select **vanta-docs**, and confirm the skills appear in the resource list. ```bash theme={"system"} codex mcp add vanta-docs --url https://developer.vanta.com/mcp ``` Verify with `codex mcp get vanta-docs --json`. Codex writes the server to `~/.codex/config.toml` under `[mcp_servers.vanta-docs]`. ```bash theme={"system"} npx skills add https://developer.vanta.com ``` Pulls every skill listed and installs the files into your agent's local config. Use this for tools that read skill files locally rather than over MCP. ## Custom skills Specific instructions for AI agents working on a focused Vanta workflow. Each skill below is self-contained — your agent loads it on demand when it detects a matching task, so you don't have to paste long prompts or remember which doc to reference. | Skill | Description | | - | - | | `build-vanta-integration` | Building, debugging, or extending a Vanta integration — auth, resource pushes, refresh-token rotation, marketplace listing. | ## Next steps The end-to-end OAuth walkthrough the `build-vanta-integration` skill encodes. Single-tenant `client_credentials` flow with custom resources and Custom Tests. Let your agent act on a live Vanta tenant once the integration code is written. Submit a finished public integration for review and publication. # Vanta API changelog Source: https://developer.vanta.com/docs/changelog Recent updates to the Vanta API and developer documentation, including new endpoints, breaking changes, and release notes. Subscribe to stay up to date on changes to the Vanta API and developer documentation, including new endpoints, breaking changes, and release notes. [Subscribe via RSS](https://developer.vanta.com/docs/changelog/rss.xml). ### Questionnaire responses are now available via API Four new endpoints manage the responses on a Customer Trust questionnaire. [`GET /customer-trust/questionnaires/{questionnaireId}/responses`](/api-reference/customer-trust/list-questionnaire-responses) lists responses, and [`GET /customer-trust/questionnaires/{questionnaireId}/responses/{responseId}`](/api-reference/customer-trust/get-questionnaire-response) retrieves one. [`PATCH /customer-trust/questionnaires/{questionnaireId}/responses/{responseId}`](/api-reference/customer-trust/update-questionnaire-response-content) updates answer content, and [`PATCH /customer-trust/questionnaires/{questionnaireId}/responses/{responseId}/owner`](/api-reference/customer-trust/update-questionnaire-response-owner) reassigns or clears the response owner. Each response carries `answerPartsSchema` and `answerPartsValues`; the legacy `answer` field is deprecated. ### Groups can now be created and imported from your IdP A new [`POST /groups`](/api-reference/groups/create-group) endpoint creates a group. [`GET /groups/importable-idp-groups`](/api-reference/groups/list-importable-idp-groups) lists identity provider groups available to import, and [`POST /groups/import-from-idp`](/api-reference/groups/import-idp-groups) imports them, returning a per-group success or error result. ### Tag categories can now be enabled per product context A new [`POST /customer-trust/tag-categories/{tagCategoryId}/product-contexts`](/api-reference/customer-trust/enable-tag-category-for-product-context) endpoint enables a tag category for a product context, such as document sharing or control sharing. [`DELETE /customer-trust/tag-categories/{tagCategoryId}/product-contexts/{productContextId}`](/api-reference/customer-trust/disable-tag-category-for-product-context) disables it. Both operations are idempotent. ### Information request evidence can now be fetched by ID A new [`GET /audits/{auditId}/information-requests/{requestId}/evidence/{evidenceId}`](/api-reference/audits/get-information-request-evidence-by-id) endpoint retrieves a single evidence item attached to an information request. Soft-deleted evidence stays fetchable; check `deletionDate` to identify deleted records. ### Group responses now include description, source, and point of contact Group objects on [`GET /groups`](/api-reference/groups/list-groups) and [`GET /groups/{groupId}`](/api-reference/groups/get-group-by-id) now include `description`, `source`, `personnelCount`, and `pointOfContact` (with `email` and `displayName`). ### Questionnaire status adds section and answer-generation states The `QuestionnaireStatus` enum on [`GET /customer-trust/questionnaires`](/api-reference/customer-trust/list-questionnaires) adds `EXTRACTING_SECTIONS`, `MAPPING_SECTIONS`, and `GENERATING_ANSWERS`. ### Issue actors can now be applications The `ActorType` enum on [`GET /issues`](/api-reference/issues/list-issues) responses adds `APPLICATION` alongside `USER` and `WORKFLOW_GENERATED`, so issue history can attribute actions to an API client. ### Trust Center compliance frameworks support TISAX 2027 The `standard` enum on [Create Trust Center compliance framework](/api-reference/trust-centers/create-trust-center-compliance-framework) and [Update Trust Center compliance framework](/api-reference/trust-centers/update-trust-center-compliance-framework) adds `tisax2027`. ### Document and Trust Center media downloads support YAML [`GET /documents/{documentId}/uploads/{uploadedFileId}/media`](/api-reference/documents/download-file-for-document) and [`GET /trust-centers/{slugId}/resources/{resourceId}/media`](/api-reference/trust-centers/get-uploaded-media-for-trust-center-document) now declare `application/yaml` and `text/x-yaml` response content types for YAML files. ### Issue snapshots now expose approval progress On [`GET /audits/{auditId}/issues/items`](/api-reference/audits/list-snapshotted-issues-for-an-audit), snapshotted issues now include a nullable `approvalProgress` object with `approvedCount` and `totalApprovers`, and the snapshot `status` enum adds `PENDING_REVIEW`. ### Rate limits raised on several Auditor API endpoints Rate limits increased from 10 to 50 requests per minute on [Update audit evidence](/api-reference/audits/update-audit-evidence), [Get framework codes for an audit](/api-reference/audits/get-framework-codes-for-an-audit), [Delete an information request for an audit](/api-reference/audits/delete-an-information-request-for-an-audit), and [Share information request list with customer](/api-reference/audits/share-information-request-list-with-customer). Limits increased from 10 to 25 requests per minute on [Create a comment for audit evidence](/api-reference/audits/create-a-comment-for-audit-evidence), [Update a comment for an information request](/api-reference/audits/update-a-comment-for-an-information-request), and [Delete a comment for an information request](/api-reference/audits/delete-a-comment-for-an-information-request). On the Manage Vanta API, [`POST /contracts`](/api-reference/contracts/upload-contract) now documents a limit of 10 requests per minute. ### Vendor assessment types are now available via API New `GET /vendor-assessment-types` and `GET /vendor-assessment-types/{assessmentTypeId}` endpoints list and retrieve vendor assessment types, filterable by status (`ACTIVE` or `ARCHIVED`). See the [Vendor Assessment Types reference](/api-reference/vendor-assessment-types/list-assessment-types). ### Auditors can now record control assessments via API A new `PUT /audits/{auditId}/controls/{controlId}/assessment` endpoint records an auditor's assessment and justification for a control within an IRL audit. See the [Upsert a control's assessment within an audit](/api-reference/audits/upsert-a-controls-assessment-within-an-audit) reference. ### Audit evidence items and comments can now be fetched by ID Three new endpoints get a single record by ID: [`GET /audits/{auditId}/evidence/{auditEvidenceId}`](/api-reference/audits/get-an-audit-evidence-item-by-id) for an audit evidence item, [`GET /audits/{auditId}/evidence/{auditEvidenceId}/comments/{commentId}`](/api-reference/audits/get-an-audit-evidence-comment-by-id) for an evidence comment, and [`GET /audits/{auditId}/information-requests/{requestId}/comments/{commentId}`](/api-reference/audits/get-an-information-request-comment-by-id) for an information-request comment. ### New webhooks fire when audit evidence enters or leaves scope [`v1.evidence.created`](/api-reference/evidence/evidence-created) fires when an evidence item comes into scope for an audit, and [`v1.evidence.deleted`](/api-reference/evidence/evidence-deleted) fires when an evidence item leaves scope (soft-deleted). ### `v1.evidence.status-changed` can now fire with unchanged status [`v1.evidence.status-changed`](/api-reference/evidence/evidence-status-changed) can now fire with `oldStatus` equal to `newStatus`. ### Trust Center responses now expose control status visibility settings `TrustCenter` responses now include a new `controlVisibilityMode` field, and `TrustCenterControlCategory` responses include new `visibility` and `statusVisibilityOverride` fields. The [Update Trust Center control category](/api-reference/trust-centers/update-trust-center-control-category) endpoint accepts both new fields. ### Customer Trust tag category filter now supports `CONTROL_SHARING` [`GET /customer-trust/tag-categories`](/api-reference/customer-trust/list-tag-categories) now accepts `CONTROL_SHARING` in the `productContextIdsMatchesAny` query filter. ### `assessments` array only includes in-scope segments On [`GET /audits/{auditId}/controls`](/api-reference/audits/list-audit-controls), the `assessments` array now contributes an entry only for segments the control is in scope for. ### IRL audits can now be duplicated into a new engagement A new [`POST /audits/duplicate`](/api-reference/audits/duplicate-an-irl-audit) endpoint copies an existing IRL audit, including its information requests, into a new engagement with new dates and auditor roster. ### Audit controls now include per-segment assessments [`GET /audits/{auditId}/controls`](/api-reference/audits/list-audit-controls) now returns an `assessments` array with the auditor's `assessmentState` and `justification` for each audit segment. ### Framework enums now include NIST 800-171 R3 and BSI C5 The Manage Vanta API and Auditor API `Framework` enum adds `NIST_171_R3`, and the Manage Vanta API `FrameworkKey` enum adds `nist171r3` and `bsic5`. See the [Frameworks reference](/api-reference/frameworks/list-available-frameworks) and [Audits API reference](/reference/audits/overview). ### Contracts now support an `externalId` for idempotent uploads [`POST /customer-trust/contracts`](/api-reference/contracts/upload-contract) now accepts and returns an optional `externalId`. Repeat uploads with the same `externalId` return `409`. ### Trust Center viewer NDA response no longer includes DocuSign `webhookId` The `ndaInfo.docuSign.webhookId` field has been removed from [Trust Center viewer](/api-reference/trust-centers/get-trust-center-viewer) responses. `envelopeId`, `accountId`, and `accountBaseUrl` still identify the DocuSign envelope. ### Vendor assessments API is now GA [`GET /v1/vendors/{vendorId}/assessments`](/api-reference/vendors/list-assessments-by-vendor-id) and [`GET /v1/vendors/{vendorId}/assessments/{assessmentId}`](/api-reference/vendors/get-assessment-by-id) are now generally available and include the assessment-level `owner` field. ### Deactivated controls can now be listed via API A new [`GET /v1/controls/deactivated-controls`](/api-reference/controls/list-deactivated-controls) endpoint returns paginated deactivated controls. [`GET /v1/controls/controls-library`](/api-reference/controls/list-vanta-controls-from-the-library) will be deprecated in a future release. ### Trust Center compliance frameworks can now be managed via API New endpoints list, create, update, and delete Trust Center compliance frameworks, and upload a framework badge image. See the [Trust Center compliance frameworks reference](/api-reference/trust-centers/list-trust-center-compliance-frameworks). ### Trust Center chatbot conversations are now available via API `GET /trust-centers/{slugId}/chatbot/conversations` lists Trust Center chatbot conversations, and `GET /trust-centers/{slugId}/chatbot/conversations/{conversationId}` returns the messages in a conversation. ### Trust Center controls now support bulk operations New endpoints bulk add or remove tags on Trust Center controls, bulk edit controls in a category, and reorder controls and control categories. ### More Trust Center settings can now be managed via API New endpoints list and set the data collected shown on your Trust Center, upload a favicon, set videos, send viewer invite reminders, and manage Trust Center FAQ categories. ### Data deletion requests can now be created via API A new `POST /customer-trust/deletion-requests` endpoint creates a data deletion request. ### Vanta issues are now available via API [`GET /issues`](/api-reference/issues/list-issues) lists issues, and [`GET /issues/{issueId}`](/api-reference/issues/get-issue-by-id) returns a single issue. ### Webhooks now include a Control domain for audit comment events Webhook events now include a **Control** domain covering audit control comment events, delivered only to [Audit Partner](/reference/audits/overview) accounts during an active audit engagement. See the [Webhooks overview](/reference/webhooks/overview). ### Auditors can now manage control comments via API New [`POST`](/api-reference/audits/create-a-comment-for-a-control-within-an-audit), [`PATCH`](/api-reference/audits/update-a-comment-for-a-control-within-an-audit), and [`DELETE`](/api-reference/audits/delete-a-comment-for-a-control-within-an-audit) endpoints at `/audits/{auditId}/controls/{controlId}/comments` let auditors create, update, and delete comments on a control. Delivered only to Audit Partner accounts during an active audit engagement. ### Audit integrations and organization details are now available via API Three new read endpoints give auditors more context during an engagement: [`GET /audits/{auditId}/integrations`](/api-reference/audits/list-integrations-for-an-audit), [`GET /audits/{auditId}/organization/information`](/api-reference/audits/get-organization-information-for-an-audit), and [`GET /audits/{auditId}/organization/notifications`](/api-reference/audits/get-organization-notification-settings-for-an-audit). Available only to Audit Partner accounts during an active audit engagement. ### Security reviews now include assessment type and owner `GET /v1/vendors/{vendorId}/security-reviews` responses now include `assessmentType` and `owner` (`id`, `type`, `displayName`, `email`). `owner` is `null` when unassigned; `email` is populated for user owners and `null` for team owners. ### Information request history now tracks audit duplication Information request history activities now include two new fields: `sourceInformationRequestId` (the request this one was copied from) and `sourceAuditId` (the audit it was duplicated from). Both are populated only for audit-duplication activities and null otherwise. See the [Audits API reference](/reference/audits/overview). ### Event log reference now includes new action types The [event log reference](/reference/manage-vanta/event-log-reference) adds `UNDELETE_PROGRAM_SEGMENT` and `REMOVE_DATA_SUBJECT_REQUEST_RELATIONSHIP_OPTION` to the list of action types. `PROVIDE_JUSTIFICATION_FOR_AUDIT_CONTROL_ASSESSMENT` was removed. ### Integration category and tag enums renamed `AuditIntegrationCategory` was renamed to `AuditIntegrationTag`, and `AuditIntegrationServiceCategory` was renamed to `AuditIntegrationCategory`. Update generated clients that reference the old schema names. ### Issue sort field values changed to camelCase `IssueSortField` enum values on the Issues endpoints changed from `DUE_DATE`, `CREATED_AT`, `DETECTED_AT`, `LAST_MODIFIED_AT`, `STATUS`, `SEVERITY` to `dueDate`, `createdDate`, `detectedDate`, `lastModifiedDate`, `status`, `severity`. Update any clients that hardcoded the old values. ### Vendor `accountManagerEmail` max length reduced The `maxLength` on the Vendor `accountManagerEmail` field was reduced from 2000 to 100 characters. Requests with longer values will be rejected. ### Issue `detectedDate` is now non-nullable The `detectedDate` field on issue responses is no longer marked nullable in the OpenAPI spec. Every issue has a detected timestamp. ### Risk scenario controls can now be managed via API New endpoints link and manage controls on a risk scenario: [`GET /risk-scenarios/{riskScenarioId}/controls`](/api-reference/risk-scenarios/list-risk-scenario-controls) lists a scenario's controls, [`POST /risk-scenarios/{riskScenarioId}/controls`](/api-reference/risk-scenarios/add-a-control-to-a-risk-scenario) adds a control, [`PATCH /risk-scenarios/{riskScenarioId}/controls/{controlId}`](/api-reference/risk-scenarios/change-a-risk-scenario-controls-controltype) changes a control's `controlType`, and [`DELETE /risk-scenarios/{riskScenarioId}/controls/{controlId}`](/api-reference/risk-scenarios/remove-a-control-from-a-risk-scenario) removes a control. ### Trust Center resources can now be organized into categories New endpoints list, add, reorder, update, and delete Trust Center resource categories. See the [Trust Center resource categories reference](/api-reference/trust-centers/list-trust-center-resource-categories). ### Trust Center viewer access can now be updated via API A new `PATCH /trust-centers/{slugId}/viewers/{viewerId}` endpoint updates a viewer's access on a Trust Center without removing and re-adding them. ### Trust Center FAQ responses now include category Trust Center FAQ endpoints now return the FAQ's `category` (id and name). ### Test snapshot evidence now includes more detail The [test-snapshot evidence detail](/api-reference/audits/get-test-snapshot-detail-for-an-evidence-row) endpoint now returns two new fields. `apiRequests` lists HTTP requests captured during API introspection tests. `outOfScopeResources` lists resources excluded at the test level (customer-disabled) and the framework level (segment configuration). ### Audit issues now support more filters `GET /audits/{auditId}/issues/items` now accepts `createdAfterDate`, `createdBeforeDate`, `detectedAfterDate`, and `detectedBeforeDate` query parameters, and `orderBy` now accepts `detectedAt`. ### Code changes date filters were renamed The `startDate` and `endDate` query parameters on `GET /audits/{auditId}/assets/code-changes` were renamed to `closedAfterDate` and `closedBeforeDate` for consistency with other Auditor API endpoints. Update any clients that hardcoded the old names. ### Event log reference now includes more actions and targets The [event log reference](/reference/manage-vanta/event-log-reference) now lists new action types covering Trust Center FAQ and resource categories, program segments, risk register updates, subscription renewals, in-app purchases, and Trust Center viewer reminders. It also adds three new target types: `TRUST_CENTER_FAQ_CATEGORY`, `TRUST_CENTER_RESOURCE_CATEGORY`, and `QUESTIONNAIRE_AUTOMATION`. ### Legacy Auditor API list endpoints are now deprecated `GET /audits/{auditId}/monitored-computers`, `GET /audits/{auditId}/people`, `GET /audits/{auditId}/vendors`, `GET /audits/{auditId}/vulnerabilities`, `GET /audits/{auditId}/vulnerability-remediations`, and `GET /audits/{auditId}/vulnerable-assets` are deprecated and work for legacy audits only, not controlled audit view. Controlled audit view uses `personnel/people`, `personnel/computers`, and `managed-vendors` instead. ### Auditors can now access code changes via API A new [`GET /audits/{auditId}/assets/code-changes`](/api-reference/audits/list-code-changes-for-an-audit) endpoint returns the pull requests visible to auditors during an audit engagement. Each record includes the PR title, identifier, repository, source (GitHub, GitLab, Bitbucket, or Azure DevOps), and opened/closed dates. Supports search, source filtering, date-range filtering, and cursor pagination. ### Vanta event logs are now available via API A new [`GET /event-logs`](/api-reference/event-logs/list-event-logs) endpoint lists audit events from your Vanta account, including the actor, date, and event type. ### Audit issue snapshots are now available via API Two new endpoints surface the issues an auditor sees during an audit: [list snapshotted issues](/api-reference/audits/list-snapshotted-issues-for-an-audit) and [list audit snapshots](/api-reference/audits/list-snapshotted-issues-for-an-audit-1). ### Test snapshot evidence detail is now available via API A new [endpoint](/api-reference/audits/get-test-snapshot-detail-for-an-evidence-row) returns rich detail for a single test-snapshot evidence row attached to an information request, including test metadata, integrations, SLA remediation policy, and the raw test data captured at snapshot time. ### Knowledge Base resources now include Trust Center category Knowledge Base resource endpoints now include a `categoryId` field for the Trust Center category a resource is filed under. Applies to `REQUEST_ACCESS` and `PUBLIC` resources. ### Risk scenarios now include an identification date Risk scenario responses now include `identificationDate`, matching the "Identified Date" field in the Vanta UI. The value defaults to the scenario's creation time when not explicitly set. ### Knowledge Base webpage resources now have stricter validation Webpage resource `title` now requires at least one character, and `url` is validated as a URI. Existing valid payloads are unaffected. ### Welcome to the Vanta developer changelog Future updates to the Vanta API and developer documentation will be listed here. # Vanta API authentication Source: https://developer.vanta.com/docs/concepts/authentication How Vanta authenticates API clients, the OAuth grant types each application type uses, and the nuances of tokens, refresh, and revocation. Every Vanta API request is authenticated with a short-lived **OAuth 2.0 bearer token**. Which OAuth flow you use — and the shape of the credentials you exchange — depends on the **application type** you create in the Developer Console. This page explains the underlying model so you can pick the right flow, understand the tradeoffs, and avoid the foot-guns that aren't obvious from the per-quickstart instructions. ## Overview Every Vanta API client is registered in the **Developer Console** as an **Application**. Each Application has a `client_id` and a `client_secret`, plus an **app type** that determines which OAuth grant types and scopes it can use. Clients exchange those credentials at a single token endpoint — `POST https://api.vanta.com/oauth/token` — for an `access_token`, then send that token as `Authorization: Bearer ` on every API request. Tokens last one hour. After that you either request a fresh one (machine-to-machine flows) or refresh it (per-customer OAuth flows). Vanta does **not** support API keys, basic auth, or session cookies for the API. Every authenticated request goes through the OAuth bearer token model below. ## Application types Vanta exposes four application types, mapped to two OAuth 2.0 grant types. The grant type — not the app type — determines the shape of the auth flow. | Application type | Grant type | Token is scoped to | Refresh tokens | | - | - | - | - | | **Manage Vanta** | `client_credentials` | Your own Vanta tenant | No | | **Build Integrations** (Private) | `client_credentials` | Your own Vanta tenant | No | | **Build Integrations** (Public) | `authorization_code` | A specific customer's tenant | Yes | | **Auditor API** | `client_credentials` | Your auditor firm's audits | No | Used by **Manage Vanta**, **Build Integrations** (Private), and **Auditor API** apps. There is no end-user; your server holds the `client_id` and `client_secret` and exchanges them directly for an access token. ```http theme={"system"} POST https://api.vanta.com/oauth/token Content-Type: application/json { "client_id": "vci_...", "client_secret": "vcs_...", "scope": "vanta-api.all:read", "grant_type": "client_credentials" } ``` Response: ```json theme={"system"} { "access_token": "vat_...", "expires_in": 3600, "token_type": "Bearer" } ``` Notice there's **no `refresh_token`** — when the access token expires, you just exchange your client credentials again for a fresh one. Most integrations request a new token at the top of each scheduled run. Used only by **Build Integrations** (Public) apps (i.e. integrations published in the [Vanta marketplace](https://app.vanta.com/integrations)). A customer clicks **Allow** in their browser, Vanta redirects them back to you with a short-lived `code`, and your server exchanges that `code` for a per-customer `access_token` plus a `refresh_token`. The flow: 1. Your server redirects the customer's browser to `/oauth/authorize` on **the customer's regional app host** (`app.vanta.com`, `app.eu.vanta.com`, or `app.aus.vanta.com` — see [Base URLs and regions](#base-urls-and-regions)) with `client_id`, `scope`, `state`, `redirect_uri`, `source_id`, and `response_type=code`. 2. The customer authorizes; Vanta redirects to your `redirect_uri` with `code` and `state` query parameters. 3. Your server `POST`s to `/oauth/token` with `grant_type=authorization_code` to receive both an `access_token` and a `refresh_token`. 4. When the access token expires, your server `POST`s to `/oauth/token` with `grant_type=refresh_token` to rotate. ```http theme={"system"} POST https://api.vanta.com/oauth/token Content-Type: application/json { "client_id": "vci_...", "client_secret": "vcs_...", "code": "vac_...", "source_id": "acct1234", "redirect_uri": "https://partner-app.com/oauth/callback", "grant_type": "authorization_code" } ``` Response: ```json theme={"system"} { "access_token": "...", "refresh_token": "...", "expires_in": 3600, "token_type": "Bearer" } ``` This is the **only** authentication request that touches the browser-facing app host — and unlike `api.vanta.com`, that host is **regional**: use the customer's own region (`app.vanta.com`, `app.eu.vanta.com`, or `app.aus.vanta.com`), not always `app.vanta.com`. All token exchanges and API calls still go to `api.vanta.com` regardless of the customer's region. See [Base URLs and regions](#base-urls-and-regions). For the full request shape — including the redirect URI rules, error codes, and the `source_id` parameter — see the [Build a Public Integration quickstart](/docs/quickstart/build-integration). ## Scopes All applications authenticate against the same `/oauth/token` endpoint, but the **scopes** you can request depend on your app type. Requesting a scope that doesn't match your app type returns an `invalid_scope` error. The full per-app scope matrix lives in the [API reference](/reference/overview#scopes). At a high level: * **Manage Vanta apps** — `vanta-api.all:read`, `vanta-api.all:write`, `vanta-api.documents:upload`, plus vendor- and issue-specific scopes. * **Build Integrations apps** (private and public) — `connectors.self:read-resource`, `connectors.self:write-resource`, `self:read-document`, `self:write-document`. * **Auditor apps** — `auditor-api.audit:read|write`, `auditor-api.auditor:read|write`. Always request the **minimum** scopes your tool needs. Scopes are validated at token-exchange time, so an over-scoped token is a real attack surface even when most of your code paths only read. ## Token lifecycle The OAuth flows themselves are standard. The behavior **around** those flows is where most production integrations get bitten. The rules below apply to every app type. Vanta only allows a **single active `access_token` per Application**. Requesting a new token with the same `client_id` and `client_secret` immediately revokes the previous one — any in-flight requests using the old token will fail with `401 Unauthorized`. Concretely, this means: * **Don't run two processes that both mint tokens** for the same Application. They'll race, mutually invalidate each other, and you'll see intermittent `401`s. * **For `client_credentials` apps**, request the token at the **start** of a sync run and reuse it for the entire run. Don't refetch per request. * **For `authorization_code` apps**, this rule applies **per `source_id`** (per customer authorization), not globally — different customers get independent tokens. ### Token expiration `expires_in` is `3600` seconds (1 hour). After that, requests return `401`. The refresh path differs by grant type: * **`client_credentials`** — re-exchange your `client_id` and `client_secret` for a new token. There's no refresh token; the credentials *are* the refresh. * **`authorization_code`** — exchange the `refresh_token` you received during initial authorization for a new `access_token` / `refresh_token` pair. ### Refresh token rotation Applies only to **Build Integrations** (Public) apps. `client_credentials` apps have no refresh token — see [Token expiration](#token-expiration) above. Every successful refresh returns a **new** `refresh_token`. The previous refresh token stays valid for **3 hours** after first use, then expires. Persist the new `refresh_token` immediately on every refresh. If your refresh handler crashes after issuing the request but before saving the result, the old token still works for up to 3 hours — long enough to recover without forcing the customer to re-authorize, but only if you actually retry. The 3-hour window is specifically designed to tolerate transient failures. Configure automatic retries on `5xx` responses and network errors during refresh; if you don't, a single bad request can lock a customer out and force a full re-auth. ### Authorization code expiration Applies only to **Build Integrations** (Public) apps — `client_credentials` apps never exchange a `code`. After Vanta redirects the customer back to your `redirect_uri` with a `code`, you have **30 seconds** to exchange it at `/oauth/token`. After that the code is dead and the customer has to start the OAuth flow over. In practice this is only a problem if your callback handler is slow (cold-start Lambdas, blocking on a database write before the token exchange). Do the token exchange first, then persist. ### Request body encoding Vanta's `/oauth/token` endpoint expects a `Content-Type: application/json` body. Most off-the-shelf OAuth client libraries default to `application/x-www-form-urlencoded` per RFC 6749 — you'll need to override that. If you see `invalid_request` or `invalid_client` errors despite using correct credentials, check the body encoding first. ### Rate limits `/oauth/token` is limited to **5 requests per minute** across all app types. This is shared across token issuance, refresh, and (for Public) the suspend endpoint. It's deliberately low because a healthy integration rarely needs more than one token per hour — if you're hitting the limit, you're probably re-minting per request rather than per run. ## Revoking access To revoke access, **rotate the `client_secret`** in the Developer Console (which immediately invalidates any active token issued with the old secret) or delete the Application entirely. When a customer disconnects your **Build Integrations** (Public) integration on **your** side (uninstall, account deletion, support escalation), you must call the **Suspend API** so Vanta cleans up its side and revokes the token: ```http theme={"system"} POST https://api.vanta.com/v1/oauth/token/suspend Content-Type: application/json { "token": "", "client_id": "vci_...", "client_secret": "vcs_..." } ``` Suspend is **idempotent** — calling it on an already-revoked token returns `200`. Calling it with a token that doesn't belong to your `client_id` returns `401`. ## Credential hygiene Rules that apply across every app type: * **Never put `client_secret`, `access_token`, or `refresh_token` in source control or client-side code.** All token exchanges must happen on a server you control. * **Rotate `client_secret` when team members leave** or any time you suspect a leak. Rotation is supported from the Developer Console. For **Build Integrations** (Public) apps specifically, rotating the secret does **not** invalidate active customer access or refresh tokens — only new token mints. The following two rules apply only to **Build Integrations** (Public) apps, since non-public apps have no per-customer tokens and never touch the browser redirect. * **Store per-customer tokens encrypted at rest.** A breach of one customer's tokens shouldn't compromise others. * **Treat `state` validation as mandatory.** Compare the returned `state` against the value you stored in the user's session before exchanging the code; abort if they don't match. This is your CSRF protection. ## Base URLs and regions The **API host** and the **browser-facing app host** follow different rules — don't assume they're regional the same way. **Token exchange and API calls always go to the same host**, regardless of the tenant's region: * `https://api.vanta.com` for standard Vanta tenants — US, EU, and AU alike * `https://api.vanta-gov.com` for **Vanta Gov** tenants `api.eu.vanta.com` and `api.aus.vanta.com` exist but only return an HTTP `308` redirect to `https://api.vanta.com` — don't call them directly. Many HTTP and OAuth libraries don't replay a `POST` body through a redirect, so a token request to the regional hostname can fail with a confusing plain-text `308` response instead of a normal error. **The browser-facing app host (`/oauth/authorize`, the Developer Console, the customer's dashboard) is regional** — each region is a genuinely separate host, not a redirect: | Region | App host | | - | - | | United States | `https://app.vanta.com` | | Europe | `https://app.eu.vanta.com` | | Australia | `https://app.aus.vanta.com` | | Vanta Gov | `https://app.vanta-gov.com` | For **Build Integrations** (Public) apps: redirect the customer to **their own** regional app host, not always `app.vanta.com`. Sending an EU or AU customer to `app.vanta.com` to authorize can fail outright or hit domain/session issues specific to that region. Everything else — grant types, scopes, token lifetimes, refresh semantics — is identical across regions and deployments. See the [API reference](/reference/overview#base-urls) for the canonical base URL table. ## Common error patterns | Symptom | Likely cause | Applies to | | - | - | - | | `401 invalid_client` on token exchange | Wrong `client_id` / `client_secret`, or rotated secret with stale value cached. | All apps | | `400 invalid_request` on token exchange | Body sent as `application/x-www-form-urlencoded` instead of `application/json`. | All apps | | `400 invalid_scope` | Requested scope isn't allowed for this app type. | All apps | | Intermittent `401` mid-run | Two processes minting tokens for the same Application — they're invalidating each other. Centralize token issuance. | All apps | | `401` after token refresh | Your refresh handler isn't persisting the **new** `refresh_token`. Without persistence you fall back to the old one, which expires 3 hours after first reuse. | **Build Integrations** (Public) only | | Customer "uninstalled" but data still flowing | You didn't call the Suspend API on disconnect. Wire it into your uninstall handler. | **Build Integrations** (Public) only | | `429` on `/oauth/token` | You're minting more than 5 tokens/minute — request once per run, not per request. | All apps | | `308` / non-JSON response from `/oauth/token` | You called a regional hostname (`api.eu.vanta.com`, `api.aus.vanta.com`) instead of `https://api.vanta.com`. Call `api.vanta.com` directly — see [Base URLs and regions](#base-urls-and-regions). | All apps | | Authorization fails, or a domain/session error on the Vanta authorize screen | You redirected an EU or AU customer to `app.vanta.com` instead of their region's app host (`app.eu.vanta.com` / `app.aus.vanta.com`). The app host is regional even though the API host isn't — see [Base URLs and regions](#base-urls-and-regions). | **Build Integrations** (Public) only | ## Related Get a `client_credentials` token and call your first endpoint. The full `authorization_code` flow, including refresh and Suspend. Single-tenant `client_credentials` flow for homegrown systems. Auditor-scoped `client_credentials` flow against customer audits. The full per-app-type scope matrix. Import the collection and start testing requests in seconds. # Integrations in Vanta Source: https://developer.vanta.com/docs/concepts/integrations What an integration is in Vanta, the difference between public and private integrations, and how they work. In Vanta, an **integration** is a connection between your Vanta tenant and an external system that pushes data **into** Vanta on a recurring schedule. That data is modeled as [**resources**](/docs/concepts/resources) — user accounts, devices, vulnerabilities, training records, background checks, and custom shapes you define yourself — and Vanta runs automated tests against them to produce compliance evidence. Vanta supports 400+ prebuilt integrations for common cloud providers, identity providers, MDMs, and SaaS tools. You can also build your own integrations using the [Build Integrations API](/reference/build-integrations/overview) — either as a Vanta partner publishing to the marketplace, or as a Vanta customer connecting a system Vanta doesn't natively support. Automating workflows **inside** your own tenant — assigning control owners, querying tests, managing vendors and personnel? That's not an integration. Use the [Manage Vanta API](/reference/manage-vanta/overview) instead. ## What an integration does Every integration follows the same shape: 1. **Authenticate** with Vanta over OAuth 2.0 to get an `access_token`. 2. **Compute the full current state** of the resources it owns from the source system. 3. **Push that state** to Vanta with `PUT /v1/resources/` on a recurring cadence (typically hourly). 4. Vanta runs **automated tests** — built-in for supported resource types, or [Custom Tests](https://help.vanta.com/hc/en-us/articles/28012720726036-Creating-Custom-Tests) you author for [custom resources](/docs/concepts/resources#custom-resources) — and turns the synced data into pass/fail evidence. Everything an integration pushes goes through Vanta's [resource model](/docs/concepts/resources): built-in types like `UserAccount`, `Computer`, `Vulnerability`, `BackgroundCheck`, and `TrainingRecord` come with prebuilt tests, and `CustomResource` lets you define your own schema when none of the built-ins fit. An integration is scoped to the resources it owns. It can push that state in with `PUT /v1/resources/` and read it back with `GET /v1/resources/`, but it can't access other tenant data or change any tenant settings. ## Public vs private integrations There are two kinds of integrations, and choosing between them is the first decision you make. | | **Public integration** | **Private integration** | | - | - | - | | **Audience** | Vanta partners / ISVs | Vanta customers | | **Distribution** | Listed in the [Vanta marketplace](https://app.vanta.com/integrations); any Vanta customer can install | Single-tenant; only used inside your own Vanta account | | **OAuth flow** | Authorization code with per-customer `access_token` and `refresh_token` | Client credentials with a single `access_token` | | **Setup** | Requires becoming a [Vanta partner](/docs/guides/become-partner) and a marketplace review | Self-serve in the [Developer Console](https://app.vanta.com/settings/developer-console) | | **Data scope** | Pushes data into each customer's tenant on their behalf | Pushes data into your own tenant only | | **Custom resources & Custom Tests** | Not available. Public integrations push only [built-in resource types](/reference/build-integrations/overview), and Vanta's built-in tests run against them. | Supported. Define [custom resources](/docs/concepts/resources#custom-resources) and author [Custom Tests](/docs/concepts/tests#custom-tests) against them in your own tenant. | | **Quickstart** | [Build a Public Integration](/docs/quickstart/build-integration) | [Build a Private Integration](/docs/quickstart/build-private-integration) | ### Private integrations Private integrations are how a Vanta customer connects something that isn't already in the marketplace — a homegrown app, an on-prem system, or a SaaS tool Vanta doesn't natively support. They never get published; the integration only exists inside your tenant. Pick a private integration when: * You need to feed data from an internal or unsupported system into your own Vanta account. * You need to connect the integration to your existing Vanta tenant. * You want to layer [Custom Tests](https://help.vanta.com/hc/en-us/articles/28012720726036-Creating-Custom-Tests) on top of data Vanta wouldn't otherwise see. Both kinds of integration use the same set of endpoints under `/v1/resources/` and the same [resource model](/docs/concepts/resources). The main differences are authorization (authorization-code vs client-credentials), distribution (marketplace vs single tenant), and access to [custom resources](/docs/concepts/resources#custom-resources) and [Custom Tests](/docs/concepts/tests#custom-tests). Both are available to private integrations only, not to public integrations. ### Public integrations Public integrations are the path for software companies that want their product to be installable by **any** Vanta customer. You build it once, list it in the Vanta marketplace, and customers self-install it through OAuth — your server then pushes their data into their tenant on a schedule. Pick a public integration when: * You sell a SaaS product whose data Vanta customers want to use as evidence (identity, devices, vulnerabilities, HR, ticketing, training, vendor management, etc.). * You're willing to host a server-side OAuth client and a per-customer sync job. * You want a marketplace listing and co-marketing as part of the [Vanta Integration Partner Program](/docs/guides/become-partner). ## Integrations only use the Build Integrations API Every integration — public or private — is built against the [**Build Integrations API**](/reference/build-integrations/overview). That's the only Vanta API that accepts data being pushed in from an external system for automated compliance monitoring. Vanta exposes three APIs, each with its own application type, scopes, and surface: | API | What it does | Who uses it | | - | - | - | | [**Build Integrations**](/reference/build-integrations/overview) | Push resources and evidence into Vanta tenants. | Partners and customers building integrations. | | [**Manage Vanta**](/reference/manage-vanta/overview) | Automate workflows inside your tenant — controls, tests, vendors, personnel, documents. | Vanta customers automating their own tenant. | | [**Conduct an Audit**](/reference/audits/overview) | Run audits, manage auditors, sample evidence. | Auditor firms. | These APIs **do not mix**. An application is created in the [Developer Console](https://app.vanta.com/settings/developer-console) under exactly one type — Build Integrations, Manage Vanta, or Conduct an Audit — and that choice determines which scopes it can request and which endpoints its tokens can hit. A Build Integrations `access_token` **cannot** call Manage Vanta or Auditor endpoints, and vice versa. Requesting a scope from a different app type returns `invalid_scope`; calling an endpoint outside your app's surface returns `403`. There is no shared credential, no token swap, and no way to "promote" one app type into another. In practice this means: * An integration that pushes user accounts **cannot** also assign control owners, query test results, or manage vendors. Those live in the Manage Vanta API. * A Manage Vanta automation script **cannot** push resources or upload evidence on a customer's behalf. That lives in the Build Integrations API. * **Partners cannot use the Manage Vanta or Auditor APIs at all.** The Build Integrations API is the entire surface available to a partner. * If a single workflow needs both — for example, a customer wants to push custom resources **and** auto-assign owners to the controls those resources feed — they need two separate applications, each with its own credentials, running side by side. This separation is intentional. It keeps partner integrations scoped to data they're allowed to push, and it prevents an integration token leak from also exposing tenant-wide configuration. ## Use cases The integrations Vanta customers and partners build cluster around a handful of patterns. ### Identity and access reviews Push `UserAccount` records from an identity source — your homegrown app's user table, a niche IdP, or an HR system — so Vanta can run access reviews against the same people that auditors will ask about. This is the most common starting point for both public and private integrations. ### Device compliance Sync `Computer` records (Windows, macOS, Linux) from an MDM, agent, or asset inventory so Vanta's device-posture tests can verify disk encryption, screen lock, OS version, and antivirus status across every employee laptop. ### Vulnerability monitoring Push `Vulnerability` records from a scanner, dependency tool, or code-repo finding source. Vanta tracks SLAs, surfaces overdue vulnerabilities, and reports remediation evidence to auditors automatically. Scanners often emit thousands of findings spanning Critical, High, Medium, and Low CVEs alongside Known malware and Protestware / potentially unwanted behavior alerts. Customers overwhelmingly act on Critical and High in Vanta — those are the severities that drive compliance monitoring. If a customer's sync would exceed the [payload limits](/reference/build-integrations/overview#payload-limits), send only Critical and High, or let customers pick which severities to sync at install time. ### HR and security training monitoring Sync `BackgroundCheck` and `TrainingRecord` resources from the HRIS, background-check vendor, or LMS that owns them. Vanta links each record to the right person and produces the per-employee evidence auditors expect. ### Evidence file uploads Upload documents and evidence (`PDF`, screenshots, exports) directly to Vanta. Useful for any workflow that produces a periodic report or evidence collected in a file format. ### Custom data Vanta doesn't natively model Use a [custom resource](/docs/concepts/resources#custom-resources) to define your own schema — internal servers, on-prem appliances, change-management records, vendor review artifacts — and pair it with a [Custom Test](https://help.vanta.com/hc/en-us/articles/28012720726036-Creating-Custom-Tests) to define what "compliant" means. This is how teams cover environments and data shapes that aren't in the supported resource list. Custom resources and Custom Tests are a **private-integration feature**, available to direct Vanta customers inside their own tenant. Public marketplace integrations cannot push custom resources or author Custom Tests on a customer's behalf. ## Related Connect a homegrown app, on-prem system, or unsupported SaaS tool to your own Vanta tenant. Become a Vanta partner and publish to the marketplace. The resource model integrations push data into — built-in and custom. Endpoint reference for everything an integration can call. # Resources in Vanta Source: https://developer.vanta.com/docs/concepts/resources What a Vanta resource is, base vs custom resource types, supported custom property types, and when to model your data as a custom resource. In Vanta, a **resource** is any entity you push into Vanta from an external system — user accounts, devices, vulnerabilities, background checks, training records, or anything you model with a custom schema. Once a resource type is defined, you can sync data to it through the API and Vanta will run automated tests against it for evidence collection. Use this page when you're **building an integration that sends data into Vanta**. To manage data that Vanta-built integrations already pull in, see the [Manage resources](/docs/guides/scope-resources-at-the-integration-level) guides instead. ## Resource types Every resource is created from a **base resource type** that defines its schema: * **Base resources** — Vanta ships predefined schemas for common entities like user accounts, devices, vulnerabilities, background checks, and training records. These come with prebuilt tests, reports, and product surfaces out of the box. * **Custom resource** — a generic resource type that lets you define the entire schema yourself. Use this when none of the base resources fit the data you need to sync. Always prefer an existing base resource type when one fits your use case. Custom resources are a flexible escape hatch, not the default — picking a built-in type gives you Vanta's prebuilt tests, reports, and product surfaces for free. Full reference of every resource type Vanta accepts. ## Create a resource In the **Resources** tab, click **+ Create Resource**. Resources tab in Vanta with the + Create Resource button highlighted The Create a Resource form opens. Complete the required fields and click **Create**. * **Resource Type** is the name used to identify the resource being sent. * **Base Resource Type** defines the structure and schema of the resource. All schemas follow the JSON type definition model. * Vanta provides several base resources with predefined schemas. * These predefined properties — and any custom properties you add — can be referenced in custom tests. * Vanta also provides a generic `CustomResource` type that lets you define the entire schema yourself via the **Custom Properties** section. * **Custom Properties** extend the base resource type with additional fields. Currently supported types: `boolean`, `int32`, `string`, `timestamp`. * **Generated schema** shows the complete structure of the resource based on the base type and custom properties. It's not editable directly, but the body of every API sync request must align with it. The schema remains accessible after creation. Create a Resource form showing the generated schema preview based on base type and custom properties Created resources appear under the **Resources** tab with their corresponding **Resource ID** and schema. The **Resource ID** is the key value you'll use when making sync requests to the Vanta API. ## Custom resources A **custom resource** is a resource created from the `CustomResource` base type. Use it when none of Vanta's base resources (user accounts, devices, vulnerabilities, background checks, training records, and so on) fit the data you need to sync. Custom resources behave like any other resource once created: you sync them through the Vanta API, and Vanta runs automated tests against them for evidence collection. **Custom resources are a [private-integration](/docs/concepts/integrations#public-vs-private-integrations) feature.** They are only available to direct Vanta customers building against their own tenant. Public marketplace integrations cannot define or sync custom resources on a customer's behalf. Pairing a custom resource with a [Custom Test](/docs/concepts/tests#custom-tests) is likewise customer-tenant only. ### When to use a custom resource Reach for a custom resource when: * The entity you're syncing isn't represented by an existing base resource type. * You need to track data that doesn't map cleanly onto user accounts, devices, vulnerabilities, background checks, or training records. * You're modeling something unique to your environment — for example, a fleet of internal-only servers, a custom inventory record, or a domain-specific compliance artifact. If your data fits a base type, use that type instead. ### Pair custom resources with custom tests Vanta only runs tests against resources it knows how to evaluate. Base resources ship with prebuilt tests, but a custom resource has no tests until you create them. To get value out of a custom resource, you need to build a [Custom Test](https://help.vanta.com/hc/en-us/articles/28012720726036-Creating-Custom-Tests) that evaluates its data and reports pass/fail per resource. Without a custom test, a custom resource is just a passive data record — it won't contribute evidence to controls. ### Schema model A custom resource's schema has two parts: 1. **Default properties** — every custom resource includes: * `displayName` — human-readable name shown in Vanta * `uniqueId` — stable identifier for the resource in your system * `externalUrl` — link back to the resource in its source system 2. **Custom properties** — fields you define using JSON Type Definition (JTD) format. Always add custom properties when creating a custom resource. A custom resource without custom properties only has the three default fields and provides no useful surface to test against — if that's all you need, a different base resource type is almost certainly a better fit. #### Supported property types Custom properties must be one of: | Type | Description | | - | - | | `boolean` | `true` or `false` | | `int32` | Numeric integer values | | `string` | Text | | `timestamp` | ISO 8601 date-time values (for example, `2024-01-15T10:30:00Z`) | Custom properties must be **top-level, flat fields** on the resource. Nested properties — objects, arrays, or sub-objects inside a property — are not supported by [Custom Tests](/docs/concepts/tests#custom-tests) and cannot be referenced in pass/fail rules. If the source data is nested, flatten the value you need into a top-level scalar property before syncing. #### Example schema A minimal `Server` resource defined as a custom resource might use this JTD: ```json theme={"system"} { "properties": { "name": { "type": "string" }, "active": { "type": "boolean" }, "memory": { "type": "int32" }, "lastUpdated": { "type": "timestamp" } } } ``` This produces a resource with `name`, `active`, `memory`, and `lastUpdated` on top of the default `displayName`, `uniqueId`, and `externalUrl` fields. Each property is then available to reference in custom tests. ### Sync model Custom resources are synced through a single endpoint: ``` /v1/resources/custom_resource ``` There are two operations: * **List** (`GET`) — returns every resource currently stored under a given `resourceId`. * **Sync** (`PUT`) — replaces the full set of resources for a given `resourceId` with the payload you send. Sync is **full-state**, not incremental. Every `PUT` must contain the complete set of resources you want Vanta to monitor. Any resource omitted from a sync is treated as no longer existing and will be marked as deleted. In practice, this means your integration should compute the full current state of resources on every run and send all of them in a single `PUT`, rather than sending diffs. For request and response details — URLs, headers, parameters, and example payloads — see the [Build Integrations API reference](/reference/build-integrations/overview). ### Lifecycle A typical custom resource lifecycle looks like this: 1. **Create the resource type** in the Vanta UI under **Resources → + Create Resource**, choosing `CustomResource` as the base type and defining your custom properties. 2. **Capture the `Resource ID`** generated after creation. You'll pass it on every API call. 3. **Sync data** by `PUT`ing the full set of resources to `/v1/resources/custom_resource` on whatever cadence makes sense for your data (typically on a recurring schedule). 4. **Build custom tests** that evaluate the synced data and produce pass/fail evidence against your controls. Vanta re-runs them on every sync. ```mermaid theme={"system"} flowchart TD Create["1. Create resource type
Vanta UI → Resources →
+ Create Resource (CustomResource)"] Capture["2. Capture Resource ID
Used on every API call"] Sync["3. Sync data
PUT full state to
/v1/resources/custom_resource"] Build["4. Build custom tests
Define pass/fail logic per resource"] Evaluate{"Vanta evaluates tests
against synced resources"} Evidence["Pass / Fail evidence
collected per resource"] Create --> Capture --> Sync Sync --> Evaluate Build --> Evaluate Evaluate --> Evidence Evidence -.->|"next sync cadence"| Sync ``` ## Related Reference for the resource sync and list endpoints. Build the tests that evaluate your custom resource data. Full reference of every resource type Vanta accepts. # Tests in Vanta Source: https://developer.vanta.com/docs/concepts/tests What a test is in Vanta, the difference between built-in tests and Custom Tests, and when to reach for a Custom Test instead of a standard one. In Vanta, a **test** is an automated configuration check that evaluates the [resources](/docs/concepts/resources) in your tenant and produces pass/fail evidence against your [controls](/docs/guides/add-an-owner-to-a-control). Tests are how synced data turns into the audit-ready signal that frameworks like SOC 2, ISO 27001, and HIPAA actually require. Every test answers the same question for every resource it sees: **does this resource meet the rule, or doesn't it?** That per-resource result rolls up into an overall test status (`OK`, `NEEDS_ATTENTION`, `DEACTIVATED`, `IN_PROGRESS`, `INVALID`, `NOT_APPLICABLE`) and feeds the controls the test is mapped to. This page is about **what tests are** and **when to author your own**. To query existing test results and failing entities through the API, see [Manage failing tests](/docs/guides/query-test-results-and-filter-for-failing-resources). ## How tests work Every test follows the same shape, regardless of whether Vanta shipped it or you built it: 1. **Pick a resource type** — user accounts, devices, vulnerabilities, custom resources, etc. 2. **Apply a rule** to each record of that type (e.g. "MFA is enabled", "disk is encrypted", "`active = true` AND `lastUpdated` within 30 days"). 3. **Emit a per-resource pass/fail** with the resource's identifier, status, and reason. 4. **Roll up to a single test status** that shows on the test page and on every control the test is mapped to. 5. **Re-run on a schedule** as new sync data arrives, automatically flipping status when the underlying data changes. Tests are read-only with respect to your source systems — they evaluate data Vanta has already received from an [integration](/docs/concepts/integrations); they don't reach back out to the source. ## Built-in tests vs Custom Tests There are two kinds of tests in Vanta, and the choice between them is driven entirely by **what data you're testing**. | | **Built-in tests** | **Custom Tests** | | - | - | - | | **Authored by** | Vanta | Vanta customers (private integrations only; not available to [partners](/docs/guides/become-partner) or public integrations) | | **Available for** | Vanta-supported resource types (`UserAccount`, `Computer`, `Vulnerability`, `BackgroundCheck`, `TrainingRecord`, etc.) | Any resource type with synced data, including [custom resources](/docs/concepts/resources#custom-resources), in your own tenant | | **Setup** | Auto-created when you connect an integration that produces a supported resource | Authored in the Vanta Dashboard under **Tests → + Create custom test** | | **Logic** | Maintained and versioned by Vanta | A pass/fail rule you define against the resource's properties | | **Mutability** | Versioned by Vanta; you can deactivate but not edit | **Immutable after creation** — copy and edit the copy if you need changes | | **Framework mapping** | Pre-mapped to common framework controls | You map each Custom Test to the controls it satisfies | | **API support** | Queryable via the Manage Vanta API | Queryable via the Manage Vanta API; **no API to create them** | ### Built-in tests Built-in tests are the default. The moment you connect an integration that produces a supported resource type, Vanta auto-creates the relevant tests, runs them on the synced data, and pre-maps them to the right controls in your enabled frameworks. You don't author them, you don't maintain them, and you don't need to know what "compliant" means for `UserAccount` or `Computer` — Vanta has already encoded the audit expectations. Reach for a built-in test when: * You're syncing a [supported resource type](/reference/build-integrations/overview) and the prebuilt rule is what your auditor is going to ask about anyway. * You want test coverage to follow the framework — when a control is added or revised by Vanta, your built-in tests track with it. * You'd rather not own pass/fail logic, edge cases, or the audit-evidence story for that data. ### Custom Tests A **Custom Test** is a pass/fail rule **you** define on top of resource data Vanta is already syncing. You pick the resource type, write the rule (e.g. "all records have `active = true` AND `lastUpdated` within the last 30 days"), and Vanta evaluates it per record on every sync. Custom Test logic is evaluated **per record**. By default, every record must pass for the test to pass — one failing record fails the whole test. This reducer is **configurable** when you author the test, so you can also express rules like "at least one record must pass" or "all records must match" depending on what the control requires. ### Joining two resource types A Custom Test can pull data from up to **two resource types** — a primary resource plus one secondary — and correlate them with a join condition you define (for example, `User.email == GitHubMembership.user_email`). The secondary resource can come from the same integration as the primary or from a different one. Once joined, fields from both resources are available in the scoping conditions and in the pass/fail rule. Use a 2-resource Custom Test when the question your auditor is asking spans two data shapes — e.g. "every IdP user with production access has a corresponding active cloud account," or "every employee in the HRIS has completed the required training record." The Test Builder currently supports a maximum of one primary + one secondary resource per Custom Test. **Custom Tests only support top-level, flat properties.** Rules can reference scalar fields on the resource itself (e.g. `active`, `lastUpdated`, `data_classification`), but **nested properties are not supported** — you cannot write a rule against fields inside an object, array, or sub-object on the resource. If you need to test on a nested value, flatten it into a top-level property on the resource before syncing. Custom Tests are authored in the Vanta Dashboard under **Tests → + Create custom test**. There is no API to create them, and the feature may require a plan upgrade or add-on — see [Vanta Plans and Pricing](https://www.vanta.com/pricing) or contact your Customer Success team if the button isn't visible on the Tests page. Custom Tests are a **private-integration feature only**, available to direct Vanta customers building against their own tenant. They are **not available to [public integrations](/docs/concepts/integrations#public-vs-private-integrations)**: partners cannot author Custom Tests, cannot push [custom resources](/docs/concepts/resources#custom-resources) into customer tenants, and there is no Build Integrations API surface for either. Customers who want to test partner-supplied data must model it themselves as a custom resource inside their own tenant. **Custom Tests are immutable after creation.** If you need to change the logic, name, or description later, copy the test and edit the copy — Vanta keeps the original for audit-trail purposes. Lock in your rule before mapping the test to controls. For the full authoring walkthrough, see [Creating Custom Tests](https://help.vanta.com/hc/en-us/articles/28012720726036-Creating-Custom-Tests). ## When to use a Custom Test over a standard test Built-in tests cover the common case. Reach for a Custom Test when one of the following is true: ### You're testing a custom resource This is the headline use case. [Custom resources](/docs/concepts/resources#custom-resources) ship with **no tests at all** — Vanta doesn't know what "compliant" means for a schema you defined yourself. Until you author a Custom Test against them, custom-resource records are passive data and contribute zero evidence to your controls. If you've gone to the trouble of defining a custom resource, a Custom Test is the step that turns it into audit signal. ### You need a stricter rule than the built-in test enforces Built-in tests encode Vanta's interpretation of the framework requirement, which is usually the audit floor. If your internal policy is stricter — for example, MFA must use a hardware key rather than any second factor, or vulnerabilities of a specific CVSS range must be remediated faster than the built-in SLA — author a Custom Test that enforces your tighter rule and map it to the same control. ### Your auditor is asking for evidence on a property Vanta doesn't already test Built-in resource types support [custom properties](/docs/concepts/resources#supported-property-types) — fields you add to a built-in schema like `UserAccount` or `Computer`. The built-in tests don't know about those custom properties; only a Custom Test can read them. If a control hinges on a field you added (e.g. `requires_background_check = true`, `data_classification = "restricted"`), a Custom Test is the only way to evaluate it. The added property must be a **top-level, flat field** on the resource — Custom Tests cannot evaluate nested properties. ### You're modeling something framework-adjacent that isn't covered out of the box Internal-only servers, change-management records, vendor-review artifacts, on-prem appliances, custom inventory — anything you sync as a custom resource because Vanta doesn't natively model it. A Custom Test is what defines the compliance criteria for that data shape inside your tenant. ### You want to layer a tenant-specific rule on data Vanta already pulls in Even when Vanta has a built-in test, you may want an additional rule that's specific to your environment — for example, "every production database resource must have an `owner` tag matching an active employee." Build a Custom Test alongside the built-in one; they both contribute evidence to the controls they're mapped to. ### When **not** to use a Custom Test If your data fits a [supported resource type](/reference/build-integrations/overview) and the built-in test asks the same question your auditor will, use the built-in test. Custom Tests are a deliberate extension, not the default — every Custom Test is a rule you now own, version, and explain to an auditor. ## How tests fit with integrations and resources Tests are the third leg of the data model: 1. An [**integration**](/docs/concepts/integrations) authenticates and pushes data into Vanta. 2. That data lands as [**resources**](/docs/concepts/resources) of a built-in or custom type. 3. **Tests** evaluate those resources and emit pass/fail results. 4. Test results are mapped to **controls**, which roll up into the **frameworks** you're tracking. The implication is clean: you can't get useful test signal without resources, and resources don't produce evidence without tests. A custom resource without a Custom Test, or a Custom Test without synced resource data, both produce nothing. ## Lifecycle of a Custom Test A typical Custom Test lifecycle: 1. **Sync the data first.** The Custom Test builder only shows resource types that have at least one record synced. Push at least one record before you start authoring. 2. **Author the test** in the Vanta Dashboard under **Tests → + Create custom test**, picking the resource type and writing the per-record rule. 3. **Preview the evaluation** — confirm the resource count is non-zero and the right records are flagged passing/failing before you save. 4. **Lock in the rule.** Once saved, the test is immutable. Changes require copying the test and editing the copy. 5. **Map to controls** so failing resources surface as gaps in the frameworks you care about. 6. **Monitor and triage** via the [List Tests](/docs/guides/query-test-results-and-filter-for-failing-resources) endpoint or the Tests page; failing entities become the work queue. ```mermaid theme={"system"} flowchart TD Sync["1. Sync the data first
Push at least one record of the
resource type into Vanta"] Author["2. Author the test
Vanta Dashboard →
Tests → + Create custom test"] Preview["3. Preview the evaluation
Confirm record count and
pass/fail flags look right"] Save{"Save the test"} Locked["4. Rule locked
Test is immutable —
copy + edit to change"] Map["5. Map to controls
Failing resources surface
as gaps in frameworks"] Monitor["6. Monitor and triage
List Tests API or
Tests page work queue"] Sync --> Author --> Preview --> Save Save --> Locked --> Map --> Monitor Monitor -.->|"need a change?"| Author ``` ## Related Query test results and filter for failing resources via the API. The data model tests evaluate — built-in resource types and custom resources. How resource data gets into Vanta in the first place. Step-by-step authoring guide in the Vanta Help Center. # Assign a control owner Source: https://developer.vanta.com/docs/guides/add-an-owner-to-a-control Make a specific Vanta user accountable for a framework control's compliance status, using the Manage Vanta API. This guide assigns a Vanta user as the owner of a framework control with `POST /v1/controls/{controlId}/set-owner` on the Manage Vanta API. Use the build prompt below to generate a scheduled job that keeps every control attached to a current employee — reassigning controls whose owner is null, departed, or pointing at an orphaned user id. ## Before you begin This guide is for Vanta admins managing data inside their own Vanta account. You'll need: * A Manage Vanta [API token](/docs/quickstart/manage-vanta). * The token must have scopes `vanta-api.all:read` and `vanta-api.all:write`. * The user you're assigning must already exist in Vanta. **Your terminal** — call [`GET /v1/controls`](/reference/manage-vanta/overview) and pick the control you want to assign. ```bash Terminal theme={"system"} curl 'https://api.vanta.com/v1/controls?pageSize=100&frameworkMatchesAny=soc2' \ -H 'Accept: application/json' \ -H 'Authorization: Bearer YOUR_TOKEN' ``` Response ```json theme={"system"} { "results": { "data": [ { "id": "database-replication-utilized", "externalId": "BCD-4", "name": "Database replication utilized", "owner": { "id": "5fc82421a228f6b6f713547d", "displayName": "Admin Admin" } } ], "pageInfo": { "hasNextPage": true, "endCursor": "..." } } } ``` Copy the `id` field — **not** `externalId`. Token is expired (one-hour lifetime), missing, or lacks `vanta-api.all:read`. Mint a fresh one — see [Authentication → Token expiration](/docs/concepts/authentication#token-expiration). Filter the response client-side by `name` or `externalId`, paginate with `pageCursor` if `hasNextPage` is `true`, or copy the ID directly from the [Controls page](https://app.vanta.com/controls) URL. **Your terminal** — call [`GET /v1/people`](/reference/manage-vanta/overview) to find the user you want to assign as owner. Filter to `CURRENT` employees so you don't pick someone who's offboarded. ```bash Terminal theme={"system"} curl 'https://api.vanta.com/v1/people?pageSize=100&employmentStatusMatchesAny=CURRENT' \ -H 'Accept: application/json' \ -H 'Authorization: Bearer YOUR_TOKEN' ``` Response ```json theme={"system"} { "results": { "data": [ { "id": "611fd13785dbc71bb89fd401", "emailAddress": "developers@vanta.com", "name": { "display": "Alejandro Ocampo" }, "employment": { "status": "CURRENT", "jobTitle": "Security Engineer" } } ] } } ``` Copy the `id`. You'll send it as `userId` in the next step. Confirm `employment.status` is `CURRENT` — `FORMER` users will be rejected by `set-owner`. Filter client-side by `emailAddress` (most reliable), or paginate with `pageCursor` if `hasNextPage` is `true`. If they're missing entirely, they may not be provisioned in Vanta yet — check the [People page](https://app.vanta.com/people/people). They've been offboarded and aren't eligible to own controls. Pick a `CURRENT` user instead. **Your terminal** — `POST /v1/controls/{controlId}/set-owner` with the user ID in the body. ```javascript Node.js theme={"system"} const CONTROL_ID = "YOUR_CONTROL_ID"; const USER_ID = "YOUR_USER_ID"; const res = await fetch( `https://api.vanta.com/v1/controls/${CONTROL_ID}/set-owner`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: "Bearer YOUR_TOKEN", }, body: JSON.stringify({ userId: USER_ID }), }, ); console.log(await res.json()); ``` ```python Python theme={"system"} import requests CONTROL_ID = "YOUR_CONTROL_ID" # id from Step 1 USER_ID = "YOUR_USER_ID" # id from Step 2 r = requests.post( f"https://api.vanta.com/v1/controls/{CONTROL_ID}/set-owner", headers={"Authorization": "Bearer YOUR_TOKEN"}, json={"userId": USER_ID}, ) r.raise_for_status() print(r.json()) ``` ```bash Terminal theme={"system"} CONTROL_ID="YOUR_CONTROL_ID" # id from Step 1 USER_ID="YOUR_USER_ID" # id from Step 2 curl -X POST "https://api.vanta.com/v1/controls/$CONTROL_ID/set-owner" \ -H 'Content-Type: application/json' \ -H 'Accept: application/json' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -d "{\"userId\": \"$USER_ID\"}" ``` Expected response (`200`) — the full control object with the new owner: ```json theme={"system"} { "id": "database-replication-utilized", "externalId": "BCD-4", "name": "Database replication utilized", "owner": { "id": "611fd13785dbc71bb89fd401", "emailAddress": "developers@vanta.com", "displayName": "Alejandro Ocampo" }, "domains": ["BUSINESS_CONTINUITY_&_DISASTER_RECOVERY"] } ``` `set-owner` overwrites any existing owner. The control ID is wrong. Most often this is because you copied `externalId` (e.g. `BCD-4`) instead of `id` (e.g. `database-replication-utilized`). Re-run Step 1 and copy `id`. The `userId` is invalid or the user is ineligible — typically because their `employment.status` is `FORMER`. Re-fetch with `employmentStatusMatchesAny=CURRENT` and pick a different user. Your token has `vanta-api.all:read` but not `vanta-api.all:write`. Mint a token with both scopes. **Unassign with `null`.** Pass `{ "userId": null }` to remove the owner without replacing them. ## Congratulations You've assigned a Vanta user as the accountable owner of a framework control. That user will now receive notifications and reminders for the control, and the change is captured in your audit log. ## Next steps Reassign every control owned by a departing teammate before you remove them. React in real time when ownership or control status changes. Import the collection and run `set-owner` against a sandbox in seconds. Browse every Manage Vanta endpoint — controls, tests, documents, people. # Add owners to resources Source: https://developer.vanta.com/docs/guides/add-owners-to-resources Use the Vanta API to update the owner and descriptions on your resources. ## Before you begin This guide is for Vanta admins managing data inside their own Vanta account. You'll need: * A Manage Vanta [API token](/docs/quickstart/manage-vanta). * The token must have scopes `vanta-api.all:read` and `vanta-api.all:write`. * At least one connected integration whose resources need owners or descriptions. Inventory resources need an active owner and a text description to pass the [Inventory items have active owners](https://app.vanta.com/tests/inventory-list-owners) and [Inventory items have descriptions](https://app.vanta.com/tests/inventory-list-descriptions) tests. Owners must be `CURRENT` employees — Vanta will reject `FORMER` users. Onboarding a new owner across many integrations? Run Step 3 once per `(integrationId, resourceKind)` pair. The bulk-update endpoint accepts up to 50 resources per call. **Your terminal** — pick the `integrationId` and `resourceKind` you want to update. If you don't already know them, list connected integrations first with [`GET /v1/integrations`](/reference/manage-vanta/overview), then list resources filtered to `hasOwner=false`. ```bash Terminal theme={"system"} curl 'https://api.vanta.com/v1/integrations/snowflake/resource-kinds/SnowflakeDatabase/resources?hasOwner=false&isInScope=true&pageSize=50' \ -H 'Accept: application/json' \ -H 'Authorization: Bearer YOUR_TOKEN' ``` Response ```json theme={"system"} { "results": { "data": [ { "responseType": "Database", "resourceKind": "SnowflakeDatabase", "resourceId": "64dc848b6491f66d23c64df6", "connectionId": "64dbda1a6491f66d234bfd41", "displayName": "SNOWFLAKE", "owner": null, "inScope": true, "description": "Snowflake Database" } ], "pageInfo": { "hasNextPage": true, "endCursor": "..." } } } ``` Copy each `resourceId` you want to update — you'll send them in Step 3. Token is expired (one-hour lifetime), missing, or lacks `vanta-api.all:read`. Mint a fresh one — see [Authentication → Token expiration](/docs/concepts/authentication#token-expiration). Call [`GET /v1/integrations`](/reference/manage-vanta/overview) to list connected integrations, their `connectionIds`, and the `resourceKinds` they expose (e.g. `aws`, `gcp`, `snowflake`, `okta`). Add `hasDescription=false` to find resources missing a description. Some resource kinds (e.g. `SnowflakeDatabase`) auto-populate a description and won't show up in that filter. **Your terminal** — call [`GET /v1/people`](/reference/manage-vanta/overview) and filter to `CURRENT` employees so you don't pick someone who's offboarded. ```bash Terminal theme={"system"} curl 'https://api.vanta.com/v1/people?pageSize=100&employmentStatusMatchesAny=CURRENT' \ -H 'Accept: application/json' \ -H 'Authorization: Bearer YOUR_TOKEN' ``` Response ```json theme={"system"} { "results": { "data": [ { "id": "5fc82421a228f6b6f713547d", "emailAddress": "developers@vanta.com", "name": { "display": "Alejandro Ocampo" }, "employment": { "status": "CURRENT", "jobTitle": "Security Engineer" } } ] } } ``` Copy the `id`. You'll send it as `ownerId` in the next step. Filter client-side by `emailAddress` (most reliable), or paginate with `pageCursor` if `hasNextPage` is `true`. You can also copy a user's ID directly from their profile URL on the [People page](https://app.vanta.com/people/people). They've been offboarded and aren't eligible to own resources. Pick a `CURRENT` user instead. **Your terminal** — `PATCH /v1/integrations/{integrationId}/resource-kinds/{resourceKind}/resources` with an `updates` array. Each entry is keyed by the resource `id` and may set `ownerId`, `description`, and/or `inScope`. ```javascript Node.js theme={"system"} const INTEGRATION_ID = "snowflake"; const RESOURCE_KIND = "SnowflakeDatabase"; const OWNER_ID = "5fc82421a228f6b6f713547d"; const res = await fetch( `https://api.vanta.com/v1/integrations/${INTEGRATION_ID}/resource-kinds/${RESOURCE_KIND}/resources`, { method: "PATCH", headers: { "Content-Type": "application/json", Authorization: "Bearer YOUR_TOKEN", }, body: JSON.stringify({ updates: [ { id: "64dc848b6491f66d23c64df6", ownerId: OWNER_ID, description: "Primary Snowflake warehouse for analytics", }, { id: "64dc848b6491f66d23c64e26", ownerId: OWNER_ID, description: "Sample dataset – read-only", }, ], }), }, ); console.log(await res.json()); ``` ```python Python theme={"system"} import requests INTEGRATION_ID = "snowflake" RESOURCE_KIND = "SnowflakeDatabase" OWNER_ID = "5fc82421a228f6b6f713547d" r = requests.patch( f"https://api.vanta.com/v1/integrations/{INTEGRATION_ID}/resource-kinds/{RESOURCE_KIND}/resources", headers={"Authorization": "Bearer YOUR_TOKEN"}, json={ "updates": [ { "id": "64dc848b6491f66d23c64df6", "ownerId": OWNER_ID, "description": "Primary Snowflake warehouse for analytics", }, { "id": "64dc848b6491f66d23c64e26", "ownerId": OWNER_ID, "description": "Sample dataset – read-only", }, ] }, ) r.raise_for_status() print(r.json()) ``` ```bash Terminal theme={"system"} curl -X PATCH 'https://api.vanta.com/v1/integrations/snowflake/resource-kinds/SnowflakeDatabase/resources' \ -H 'Content-Type: application/json' \ -H 'Accept: application/json' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -d '{ "updates": [ { "id": "64dc848b6491f66d23c64df6", "ownerId": "5fc82421a228f6b6f713547d", "description": "Primary Snowflake warehouse for analytics" }, { "id": "64dc848b6491f66d23c64e26", "ownerId": "5fc82421a228f6b6f713547d", "description": "Sample dataset – read-only" } ] }' ``` Expected response (`200`) — a per-resource result, so you can tell which updates failed: ```json theme={"system"} { "results": [ { "id": "64dc848b6491f66d23c64df6", "status": "SUCCESS" }, { "id": "64dc848b6491f66d23c64e26", "status": "SUCCESS" } ] } ``` The bulk endpoint accepts up to **50** resources per call. Page through Step 1 and call this endpoint in batches if you have more. The `message` field tells you which update failed and why — typically because `ownerId` is `FORMER`, the `id` doesn't belong to that `(integrationId, resourceKind)`, or the resource kind doesn't support `description`. Successful entries are still applied; only fix and retry the failures. The `integrationId` or `resourceKind` is wrong. They're case-sensitive — `snowflake` and `SnowflakeDatabase` are different fields. Re-run Step 1 to confirm the exact spellings. Your token has `vanta-api.all:read` but not `vanta-api.all:write`. Mint a token with both scopes. **Single-resource update?** Use `PATCH /v1/integrations/{integrationId}/resource-kinds/{resourceKind}/resources/{resourceId}` with `{ "ownerId": "...", "description": "..." }` instead. It returns `204 No Content` on success. ## Congratulations You've assigned active owners and descriptions to your inventory resources. Those resources will now pass the **Inventory items have active owners** and **Inventory items have descriptions** tests, and the changes are captured in your audit log. ## Next steps Mark resources `inScope: false` to exclude them from tests entirely. Make a specific user accountable for the controls these resources support. Import the collection and run the bulk PATCH against a sandbox in seconds. Browse every Manage Vanta endpoint — controls, tests, documents, people, integrations. # Become an integration partner Source: https://developer.vanta.com/docs/guides/become-partner Join the Vanta Integration Partner Program to publish your integration in the Vanta marketplace and reach thousands of security-conscious customers. The Vanta Integration Partner Program is for software companies who want to build and publish a **public** integration to the [Vanta marketplace](https://app.vanta.com/integrations). Public integrations let any Vanta customer connect your product through OAuth and automatically pull data into their compliance program. Building an integration only for your own Vanta account? You don't need to become a partner — follow the [Build a private integration](/docs/quickstart/build-private-integration) quickstart instead. ## Why become a partner Joining the program turns your integration into a co-marketed, customer-installable product on a platform used by thousands of fast-growing companies. Get discovered by thousands of Vanta customers actively looking for integrations to automate their security and compliance evidence. A dedicated listing page in the in-app Vanta marketplace, with your logo, description, category, and one-click install. Joint announcements, blog features, and inclusion in Vanta's integration newsletters and customer communications when you launch. Customers stay on your product longer when it removes manual evidence collection from their audits — a meaningful retention and expansion lever. Direct access to Vanta's partnerships and engineering teams for integration design reviews, troubleshooting, and launch planning. ## Who should apply The program is a fit if you can answer **yes** to all of the following: * You sell a SaaS product that produces data Vanta customers care about — identity, devices, vulnerabilities, infrastructure, HR, ticketing, training, vendor management, etc. See [Supported resource types](/docs/concepts/resources#resource-types) for examples. * You can host a server-side OAuth client and a periodic job (typically hourly) to push data to Vanta on each customer's behalf. * You have engineering capacity for the build time, plus review and launch. * You're comfortable being listed publicly in Vanta's marketplace and supporting shared customers post-launch. ## How the process works Email [integrationpartners@vanta.com](mailto:integrationpartners@vanta.com) with: * Your company name and product URL * A short description of the integration you want to build (what data flows into Vanta, and the customer problem it solves) * The engineering contact who'll own the build Vanta's partnerships team reviews fit and responds within a few business days. If approved, you'll be provisioned a partner email of the form `[your_email]+connectors@[your_company].com` for accessing the Developer Console. Follow the [Build an Integration quickstart](/docs/quickstart/build-integration) to: * Create a **Build Integrations → Public** application in the [Developer Console](https://app.vanta.com/settings/developer-console) * Implement the OAuth 2.0 authorization-code flow, including `state` validation on callback for CSRF protection * Push your first resource (most partners start with `UserAccount`) on an hourly schedule * Wire up token refresh and the Suspend API for clean disconnects Vanta's team is available to answer questions and review your design before you go to review. Before submitting for review, complete a full OAuth flow and at least one resource sync against a live Vanta tenant. Vanta will provision a tenant for you for development and testing. Follow [List your integration](/docs/guides/list-your-integration) to send Vanta your marketing assets (logo, descriptions, customer setup guide URL) and request a marketplace review. Vanta validates the OAuth flow, the resources you push, and your customer-facing setup documentation. Most reviews complete within one to two weeks. You'll get a single consolidated round of feedback — fix and resubmit if needed. Once approved, Vanta enables your listing and any joint marketing (if approved). Customers can then discover and install your integration directly from the in-app marketplace. After launch, monitor installs and customer support feedback. ## What Vanta provides * **A partner email and Developer Console access** for creating Public Build Integrations applications and managing OAuth credentials. * **A documented API surface** — OAuth, the Build Integrations REST API. * **Design and review support** from the partnerships and engineering teams during build and review. * **A marketplace listing** with your logo, description, and a one-click install flow surfaced to every Vanta customer. ## What you're responsible for * **Building and operating** the integration — running the OAuth client, hourly sync job, and any document upload pipeline against your customers' Vanta tenants. * **Securing tokens** — `client_secret`, `access_token`, and `refresh_token` values per customer. * **Customer setup documentation** — a public page that walks shared customers through enabling the integration. * **Customer support** for shared customers when the integration breaks on your side. * **Notifying Vanta** of metadata or scope changes after launch — some changes require re-review. ## FAQ Most partners complete the build in about 1 week of engineering time. Review and marketing prep typically take one to two weeks on top of that, for a total of 2–4 weeks from intake to live listing. No. The Vanta Integration Partner Program is free to join. Private integrations cannot be automatically converted to public ones — you'll need to create a separate public app. Private integrations are best for testing your integration in your Vanta test sandbox. When you're ready to roll out to customers, create a **Build Integrations → Public** app and switch the OAuth flow over. Resource schemas and the data plane are identical between the two. Once your public integration is approved and published, it goes live to all Vanta customers at once via the marketplace. Anything Vanta supports as a resource type — `UserAccount`, computers and devices, vulnerabilities and more — plus document uploads for file-based evidence. Pick the types that match the data your product owns. Adding new scopes, changing resource types you push, or significantly changing the integration's behavior require Vanta to re-validate the listing. Cosmetic changes to your description, logo, or setup guide do not. Email [integrationpartners@vanta.com](mailto:integrationpartners@vanta.com) when in doubt. ## Next steps Email [integrationpartners@vanta.com](mailto:integrationpartners@vanta.com) with your company, product, and proposed integration. The end-to-end technical quickstart — OAuth, first resource, and verification. Submission checklist and marketplace review process. Full reference for every endpoint available to public integrations. # Create and update risk scenarios Source: https://developer.vanta.com/docs/guides/create-risk-scenarios Create risk scenarios in a specific register, set custom fields, and update them via the Manage Vanta API — including the common 400 errors that trip up most integrations. This guide creates and updates risk scenarios via `POST /v1/risk-scenarios` and `PATCH /v1/risk-scenarios/{riskScenarioId}` on the Manage Vanta API. It covers the three things most integrations trip on: targeting a specific **risk register**, setting **custom fields** with the right label and value shape, and modeling attributes (like "source of risk") that aren't in the built-in schema. ## Before you begin This guide is for Vanta admins managing risk data inside their own Vanta account. You'll need: * A Manage Vanta [API token](/docs/quickstart/manage-vanta). * Scopes `vanta-api.all:read` and `vanta-api.all:write` on the token. There is no risk-specific scope — risk scenarios are covered by the broad `vanta-api.all:*` scopes. See [API authentication](/docs/concepts/authentication). * Any custom fields you plan to set must already be defined in **Risk Management → Settings → Custom Fields** in the Vanta UI. The API fills custom field values; it can't create the field definitions. The `CreateRiskScenarioInput` schema has a fixed set of fields. There is no built-in `source` field, no built-in `jiraTicket` field, and no per-scenario "risk owner group". Anything not in the table below has to be modeled as a **custom field** (see Step 2 below): | Field | Type | Notes | | - | - | - | | `description` | string | **Required.** Short title of the risk. | | `detailedDescription` | string | Long-form context (max 10,000 chars). | | `riskId` | string | Stable identifier. Auto-generated if omitted. Reuse it to update. | | `likelihood` / `impact` | integer | Inherent risk scores, default range 1–5 (customizable in settings). | | `residualLikelihood` / `residualImpact` | integer | Post-mitigation scores. | | `categories` | string\[] | New values become new categories automatically. | | `ciaCategories` | `Confidentiality` / `Integrity` / `Availability` | | | `treatment` | `Mitigate` / `Transfer` / `Avoid` / `Accept` | | | `owner` | string | **Email address** of a Vanta user. | | `note` | string | Justification for the scores. | | `riskRegister` | string | **Name** of the register (not an id). Required if you have multiple registers. | | `customFields` | array | Label/value pairs for org-specific attributes — see Step 2 below. | | `type` | `Risk Scenario` / `Enterprise Risk` | Enterprise risks can't be attached to a register. Defaults to `Risk Scenario`. | | `identificationDate` | ISO 8601 | Defaults to creation time. | There's also a deprecated `isSensitive` boolean still accepted by the API; new integrations shouldn't rely on it. **Your terminal** — `POST /v1/risk-scenarios`. Only `description` is strictly required, but if your tenant has more than one risk register you must pass `riskRegister` **by name** (case-sensitive) or the API returns 400. ```javascript Node.js theme={"system"} const res = await fetch("https://api.vanta.com/v1/risk-scenarios", { method: "POST", headers: { "Content-Type": "application/json", Authorization: "Bearer YOUR_TOKEN", }, body: JSON.stringify({ description: "Unauthorized access to production database", riskRegister: "Default", likelihood: 3, impact: 4, treatment: "Mitigate", owner: "risk-owner@example.com", ciaCategories: ["Confidentiality"], }), }); const scenario = await res.json(); console.log(scenario.riskId); ``` ```python Python theme={"system"} import requests r = requests.post( "https://api.vanta.com/v1/risk-scenarios", headers={"Authorization": "Bearer YOUR_TOKEN"}, json={ "description": "Unauthorized access to production database", "riskRegister": "Default", "likelihood": 3, "impact": 4, "treatment": "Mitigate", "owner": "risk-owner@example.com", "ciaCategories": ["Confidentiality"], }, ) r.raise_for_status() print(r.json()["riskId"]) ``` ```bash Terminal theme={"system"} curl -X POST 'https://api.vanta.com/v1/risk-scenarios' \ -H 'Content-Type: application/json' \ -H 'Accept: application/json' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -d '{ "description": "Unauthorized access to production database", "riskRegister": "Default", "likelihood": 3, "impact": 4, "treatment": "Mitigate", "owner": "risk-owner@example.com", "ciaCategories": ["Confidentiality"] }' ``` A `200` response returns the full risk scenario, including the `riskId` you'll use for later updates. `riskRegister` takes the register's **name**, not its id. Open **Risk Management → Registers** in Vanta and copy the exact name (spaces, capitalization, and punctuation all matter). Tenants with a single register can omit the field. `owner` must be the email address of an existing Vanta user, not a display name or a person id. Look up the address with `GET /v1/people` filtered to `employmentStatus=CURRENT`. Pass `type: "Enterprise Risk"` and omit `riskRegister` — enterprise risks aren't attached to a register. Requires the Enterprise Risk Management SKU. Anything outside the built-in schema — "Source of risk", a Jira ticket URL, an internal risk tier, a business unit — is a **custom field**. Custom fields must be **defined ahead of time** in **Risk Management → Settings → Custom Fields**; the API fills values but never creates field definitions. Pass them via the `customFields` array. Each entry has a `label` (matches the field name in settings exactly, case-sensitive) and a `value` matching the field's type: * **Text / date / number / currency** — JSON string: `{ "label": "Source of risk", "value": "Internal audit finding" }` * **Picklist** — JSON array of strings: `{ "label": "Business unit", "value": ["Engineering", "Security"] }` ```bash Terminal theme={"system"} curl -X POST 'https://api.vanta.com/v1/risk-scenarios' \ -H 'Content-Type: application/json' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -d '{ "description": "Unauthorized access to production database", "riskRegister": "Default", "customFields": [ { "label": "Source of risk", "value": "Internal audit finding" }, { "label": "Jira ticket", "value": "https://your-org.atlassian.net/browse/SEC-1234" }, { "label": "Business unit", "value": ["Engineering", "Security"] } ] }' ``` The `label` you sent doesn't match any custom field defined in **Risk Management → Settings → Custom Fields**. This includes system-style identifiers like `managed_by_email` — the API does not resolve those. Open the settings page, copy the field name exactly, and retry. Custom field definitions cannot be created through the API. Your JSON value doesn't match the field's declared type. Picklist fields need an array of strings even when you're only setting one option. Text/date/number/currency fields need a plain string. There isn't one. `riskId`, `description`, `detailedDescription`, `note`, `categories`, `ciaCategories`, `treatment`, `owner`, `riskRegister`, `likelihood`, `impact`, `residualLikelihood`, `residualImpact`, `type`, and `identificationDate` (plus the deprecated `isSensitive` flag) are the only non-custom fields on a risk scenario — everything else has to be a custom field. **Your terminal** — `PATCH /v1/risk-scenarios/{riskScenarioId}`. Send only the fields you want to change; omitted fields keep their current values. `customFields` follows the same shape as create. ```javascript Node.js theme={"system"} const RISK_ID = "YOUR_RISK_ID"; const res = await fetch(`https://api.vanta.com/v1/risk-scenarios/${RISK_ID}`, { method: "PATCH", headers: { "Content-Type": "application/json", Authorization: "Bearer YOUR_TOKEN", }, body: JSON.stringify({ residualLikelihood: 2, residualImpact: 2, customFields: [ { label: "Jira ticket", value: "https://your-org.atlassian.net/browse/SEC-1234" }, ], }), }); console.log(await res.json()); ``` ```bash Terminal theme={"system"} RISK_ID="YOUR_RISK_ID" curl -X PATCH "https://api.vanta.com/v1/risk-scenarios/$RISK_ID" \ -H 'Content-Type: application/json' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -d '{ "residualLikelihood": 2, "residualImpact": 2, "customFields": [ { "label": "Jira ticket", "value": "https://your-org.atlassian.net/browse/SEC-1234" } ] }' ``` Send the field with `value: ""` (text/date/number/currency) or `value: []` (picklist). The `label` still has to match a defined field. No — changing a scenario's `type` (`Risk Scenario` ↔ `Enterprise Risk`) is not supported via `PATCH`. Requests that include `type` are rejected. Create a new scenario with the desired type and archive the old one. ## Congratulations You can now create risk scenarios in the right register, populate every organization-specific attribute via custom fields, and update scores or metadata idempotently. ## Next steps Make a specific user accountable for the controls that mitigate a risk. Same `customFields` pattern applied to the Vendors API. Import the collection and hit `POST /v1/risk-scenarios` against a sandbox. Browse every Manage Vanta endpoint — risk scenarios, controls, tests, documents, people. # Create vendors with evidence Source: https://developer.vanta.com/docs/guides/create-vendors-and-attach-documentation Add a vendor to your Vanta vendor inventory and attach a documentation file (SOC 2, DPA, security questionnaire, etc.), using the Manage Vanta API. This guide creates a vendor in your Vanta vendor inventory with `POST /v1/vendors` and attaches an evidence file (SOC 2 report, DPA, pen test, security questionnaire) with `POST /v1/vendors/{vendorId}/documents` on the Manage Vanta API. The build prompt below generates a scheduled job that reads a vendor list from disk, deduplicates by `websiteUrl`, and uploads fresh evidence files idempotently. ## Before you begin This guide is for Vanta admins managing data inside their own Vanta account. You'll need: * A Manage Vanta [API token](/docs/quickstart/manage-vanta). * The token must have scopes `vanta-api.all:read` and `vanta-api.all:write`. * The evidence file you want to attach (PDF, DOCX, JPG, PNG, or XLSX) saved locally. Bulk-importing vendors from a procurement system? Run Step 1 in a loop, capture the returned `id`, then run Step 2 once per supporting document. **Your terminal** — `POST /v1/vendors` with the vendor metadata. Only `name` is required; everything else can be filled in later via `PATCH /v1/vendors/{vendorId}`. ```javascript Node.js theme={"system"} const res = await fetch("https://api.vanta.com/v1/vendors", { method: "POST", headers: { "Content-Type": "application/json", Authorization: "Bearer YOUR_TOKEN", }, body: JSON.stringify({ name: "Acme Corp", websiteUrl: "https://acmecorp.com", category: "cloudStorage", servicesProvided: "Object storage and CDN", inherentRiskLevel: "MEDIUM", }), }); const vendor = await res.json(); console.log(vendor.id); ``` ```python Python theme={"system"} import requests r = requests.post( "https://api.vanta.com/v1/vendors", headers={"Authorization": "Bearer YOUR_TOKEN"}, json={ "name": "Acme Corp", "websiteUrl": "https://acmecorp.com", "category": "cloudStorage", "servicesProvided": "Object storage and CDN", "inherentRiskLevel": "MEDIUM", }, ) r.raise_for_status() print(r.json()["id"]) ``` ```bash Terminal theme={"system"} curl -X POST 'https://api.vanta.com/v1/vendors' \ -H 'Content-Type: application/json' \ -H 'Accept: application/json' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -d '{ "name": "Acme Corp", "websiteUrl": "https://acmecorp.com", "category": "cloudStorage", "servicesProvided": "Object storage and CDN", "inherentRiskLevel": "MEDIUM" }' ``` Expected response (`200`) — the full vendor object, including the `id` you'll need in Step 2: ```json theme={"system"} { "id": "a2f7e1b9d0c3f4e5a6c7b8d8", "name": "Acme Corp", "websiteUrl": "https://acmecorp.com", "category": { "displayName": "cloudStorage" }, "status": "MANAGED", "inherentRiskLevel": "MEDIUM", "residualRiskLevel": null, "isVisibleToAuditors": true } ``` Copy the `id` — you'll send it as the path parameter in the next step. Token is expired (one-hour lifetime), missing, or lacks `vanta-api.all:write`. Mint a fresh one — see [Authentication → Token expiration](/docs/concepts/authentication#token-expiration). The API processes the request in this order: (1) the category is applied, (2) all attributes inherited from that category are wiped, (3) the explicit attributes you sent are applied on top. This differs from the UI, which preserves both. Send the final, intended set of attributes in a single call. When the vendor's `inherentRiskLevel` warrants it, Vanta automatically creates a security review. The review must be **started** from the [Vendor page](https://app.vanta.com/vendors) — there's no API endpoint to start it. Security reviews are scoped per vendor — there is no top-level `GET /v1/security-reviews` endpoint. To enumerate every review, page through [`GET /v1/vendors`](/reference/manage-vanta/overview) and call [`GET /v1/vendors/{vendorId}/security-reviews`](/reference/manage-vanta/overview) for each vendor `id`. Plan for the [50 requests/minute Manage Vanta rate limit](/reference/manage-vanta/overview#rate-limits): a tenant with several hundred vendors takes multiple minutes to fully enumerate. Cache the result, page with `pageSize=100` to minimize round trips, and re-fetch only the vendors whose `updatedAt` changed since the last run. **Your terminal** — `POST /v1/vendors/{vendorId}/documents` as `multipart/form-data` with the file in the `file` field and a document `type` (e.g. `SOC2_REPORT`, `DPA`, `PRIVACY_POLICY`, `OTHER`). ```javascript Node.js theme={"system"} import fs from "node:fs"; const VENDOR_ID = "YOUR_VENDOR_ID"; const FILE_PATH = "./acme-soc2.pdf"; const form = new FormData(); form.append( "file", new Blob([fs.readFileSync(FILE_PATH)], { type: "application/pdf" }), "acme-soc2.pdf", ); form.append("type", "SOC2_REPORT"); form.append("title", "Acme SOC 2 Type II – 2024"); form.append("description", "Provided by Acme on 2024-09-01"); const res = await fetch( `https://api.vanta.com/v1/vendors/${VENDOR_ID}/documents`, { method: "POST", headers: { Authorization: "Bearer YOUR_TOKEN" }, body: form, }, ); console.log(await res.json()); ``` ```python Python theme={"system"} import requests VENDOR_ID = "YOUR_VENDOR_ID" FILE_PATH = "./acme-soc2.pdf" with open(FILE_PATH, "rb") as f: r = requests.post( f"https://api.vanta.com/v1/vendors/{VENDOR_ID}/documents", headers={"Authorization": "Bearer YOUR_TOKEN"}, files={"file": ("acme-soc2.pdf", f, "application/pdf")}, data={ "type": "SOC2_REPORT", "title": "Acme SOC 2 Type II – 2024", "description": "Provided by Acme on 2024-09-01", }, ) r.raise_for_status() print(r.json()) ``` ```bash Terminal theme={"system"} VENDOR_ID="YOUR_VENDOR_ID" curl -X POST "https://api.vanta.com/v1/vendors/$VENDOR_ID/documents" \ -H 'Accept: application/json' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -F 'file=@"./acme-soc2.pdf"' \ -F 'type="SOC2_REPORT"' \ -F 'title="Acme SOC 2 Type II – 2024"' \ -F 'description="Provided by Acme on 2024-09-01"' ``` Expected response (`200`) — the uploaded document metadata: ```json theme={"system"} { "id": "a2f7e1b9d0c3f4e5a6c7b8d8", "title": "Acme SOC 2 Type II – 2024", "fileName": "acme-soc2.pdf", "type": "SOC2_REPORT", "mimeType": "application/pdf", "description": "Provided by Acme on 2024-09-01", "url": "https://example.com", "creationDate": "2024-09-01T00:00:00.000Z", "uploadedBy": { "id": "66993da0cf4ba2ad40599ba7", "type": "USER" } } ``` Supported file types are `.pdf`, `.docx`, `.jpg`, `.png`, and `.xlsx`. You can't attach a link as evidence via the API today — use the [Vendor page](https://app.vanta.com/vendors) for link evidence. The `vendorId` is wrong. Re-run Step 1 and copy the `id` exactly from the response (or from the URL on the [Vendor page](https://app.vanta.com/vendors)). The request must be `multipart/form-data` — don't set `Content-Type` manually, let your HTTP client add the boundary. Pass the file with `-F` (curl), `files=` (requests), or a `FormData` body (fetch). `type` is required and must be one of Vanta's supported document types. Common values: `SOC2_REPORT`, `ISO_27001_REPORT`, `PEN_TEST`, `DPA`, `PRIVACY_POLICY`, `OTHER`. The full enum lives in the [API reference](/reference/manage-vanta/overview). **Updating an existing vendor?** Use `PATCH /v1/vendors/{vendorId}` with the same body shape (without `name` if you're not changing it). To replace stale evidence, repeat Step 2 — each upload is stored independently and the latest is shown first. ## Congratulations You've added a vendor to your Vanta inventory and attached evidence to it. The vendor is now visible on your [Vendor page](https://app.vanta.com/vendors), counts toward vendor-management tests, and the document is captured in your audit log. ## Next steps Attach organization-specific metadata — contract dates, internal owners, risk tiers — to the vendor. Make a specific user accountable for the vendor-management controls this evidence supports. Import the collection and run `createVendor` + `documents` against a sandbox in seconds. Browse every Manage Vanta endpoint — vendors, controls, tests, documents, people. # Find overdue security tasks Source: https://developer.vanta.com/docs/guides/list-users-with-overdue-security-tasks Find current employees with overdue trainings, policy acceptances, custom tasks, background checks, or device-monitoring installs, using the Manage Vanta API. This guide queries `GET /v1/people` on the Manage Vanta API for current employees with overdue security tasks — incomplete trainings, unaccepted policies, open custom tasks, missing background checks, or missing device-monitoring installs. Use the ask prompt to surface overdue tasks through the Vanta MCP server in seconds, or the build prompt to generate a scheduled job that emits one JSON line per person with the specific task types still open. ## Before you begin This guide is for Vanta admins managing data inside their own Vanta account. You'll need: * A Manage Vanta [API token](/docs/quickstart/manage-vanta). * The token must have scope `vanta-api.all:read`. * At least one source of personnel data connected to Vanta (HRIS, IDP, or manually added users). Vanta tracks recurring security tasks for every person in your organization — security training, policy acceptance, custom checklists, background checks, and device-monitoring installs. The People endpoint lets you filter for people whose tasks are `OVERDUE`, then chase them down. Wiring this into a recurring nudge (Slack reminder, email digest)? Run Step 1 on a schedule and feed the output into your notifier. Tokens expire hourly — re-mint at the top of each run. **Your terminal** — call [`GET /v1/people`](/reference/manage-vanta/overview) with `taskTypeMatchesAny` for the task types you care about, `taskStatusMatchesAny=OVERDUE`, and `employmentStatusMatchesAny=CURRENT` so you don't chase former employees. ```bash Terminal theme={"system"} curl 'https://api.vanta.com/v1/people?pageSize=50&employmentStatusMatchesAny=CURRENT&taskStatusMatchesAny=OVERDUE&taskTypeMatchesAny=COMPLETE_TRAININGS&taskTypeMatchesAny=ACCEPT_POLICIES&taskTypeMatchesAny=COMPLETE_CUSTOM_TASKS&taskTypeMatchesAny=COMPLETE_BACKGROUND_CHECKS&taskTypeMatchesAny=INSTALL_DEVICE_MONITORING' \ -H 'Accept: application/json' \ -H 'Authorization: Bearer YOUR_TOKEN' ``` Response (truncated for readability) ```json theme={"system"} { "results": { "data": [ { "id": "5fc82421a228f6b6f713547d", "emailAddress": "alex@example.com", "name": { "display": "Alex Admin" }, "employment": { "status": "CURRENT", "jobTitle": "Engineer" }, "tasksSummary": { "status": "OVERDUE", "dueDate": "2024-05-12T04:31:54.490Z", "details": { "completeTrainings": { "status": "OVERDUE", "incompleteTrainings": [{ "name": "AI_RISK_SECURITY_TRAINING" }] }, "acceptPolicies": { "status": "OVERDUE", "unacceptedPolicies": [{ "name": "Secure Development Policy" }] }, "completeBackgroundChecks": { "status": "COMPLETE" } } } } ], "pageInfo": { "hasNextPage": true, "endCursor": "..." } } } ``` `tasksSummary.details` breaks down each task type so you can build a precise nudge ("you owe AI Risk training and one policy acceptance") rather than a generic "you have overdue tasks" message. Token is expired (one-hour lifetime), missing, or lacks `vanta-api.all:read`. Mint a fresh one — see [Authentication → Token expiration](/docs/concepts/authentication#token-expiration). `COMPLETE_TRAININGS`, `ACCEPT_POLICIES`, `COMPLETE_CUSTOM_TASKS`, `INSTALL_DEVICE_MONITORING`, `COMPLETE_BACKGROUND_CHECKS`. Pass each one as a separate `taskTypeMatchesAny=` query param. `COMPLETE`, `DUE_SOON`, `OVERDUE`, `NONE`. `taskStatusMatchesAny` is **required** when you pass `taskTypeMatchesAny`. You omitted `employmentStatusMatchesAny=CURRENT`. The endpoint returns all matches by default, including offboarded people whose tasks were never completed. **Your terminal** — paginate with `pageCursor` if `hasNextPage` is `true`, then collapse each person's `tasksSummary.details` down to the specific items they owe. ```javascript Node.js theme={"system"} const URL = "https://api.vanta.com/v1/people?pageSize=50" + "&employmentStatusMatchesAny=CURRENT" + "&taskStatusMatchesAny=OVERDUE" + "&taskTypeMatchesAny=COMPLETE_TRAININGS" + "&taskTypeMatchesAny=ACCEPT_POLICIES" + "&taskTypeMatchesAny=COMPLETE_CUSTOM_TASKS" + "&taskTypeMatchesAny=COMPLETE_BACKGROUND_CHECKS" + "&taskTypeMatchesAny=INSTALL_DEVICE_MONITORING"; const res = await fetch(URL, { headers: { Authorization: "Bearer YOUR_TOKEN" }, }); const { results } = await res.json(); const overdue = results.data.map((person) => ({ name: person.name.display, email: person.emailAddress, overdueTasks: Object.entries(person.tasksSummary?.details ?? {}) .filter(([, task]) => task.status === "OVERDUE") .map(([type]) => type), })); console.log(overdue); ``` ```python Python theme={"system"} import requests url = "https://api.vanta.com/v1/people" params = [ ("pageSize", 50), ("employmentStatusMatchesAny", "CURRENT"), ("taskStatusMatchesAny", "OVERDUE"), ("taskTypeMatchesAny", "COMPLETE_TRAININGS"), ("taskTypeMatchesAny", "ACCEPT_POLICIES"), ("taskTypeMatchesAny", "COMPLETE_CUSTOM_TASKS"), ("taskTypeMatchesAny", "COMPLETE_BACKGROUND_CHECKS"), ("taskTypeMatchesAny", "INSTALL_DEVICE_MONITORING"), ] r = requests.get( url, headers={"Authorization": "Bearer YOUR_TOKEN"}, params=params, ) r.raise_for_status() for person in r.json()["results"]["data"]: overdue = [ t for t, info in (person["tasksSummary"] or {}).get("details", {}).items() if info.get("status") == "OVERDUE" ] if overdue: print(person["name"]["display"], person["emailAddress"], overdue) ``` Example collapsed output: ```json theme={"system"} [ { "name": "Alex Admin", "email": "alex@example.com", "overdueTasks": ["completeTrainings", "acceptPolicies"] } ] ``` That person has no tasks assigned (e.g. a contractor or service account marked as not-a-person). Skip them. See [Mark accounts as not a person](/docs/guides/mark-people-as-not-a-person). Read `results.pageInfo.endCursor` and `hasNextPage`. Re-call the endpoint with `pageCursor=` until `hasNextPage` is `false`. Don't try to fetch all people in one call — `pageSize` caps at 100. **Just want a count, not the list?** The same query returns `pageInfo.hasNextPage` plus a `data` array — paginate to count, or filter more aggressively (e.g. by single `taskTypeMatchesAny`) for a smaller response. ## Congratulations You've pulled the canonical list of current employees with overdue security tasks straight from Vanta. Wire this into a Slack nudge, email digest, or compliance dashboard so reminders happen without anyone clicking through the Vanta UI. ## Next steps Exclude shared mailboxes and service accounts from these task tallies. Once an employee is `FORMER`, complete the offboarding programmatically. Import the collection and run the People query against a sandbox in seconds. Browse every Manage Vanta endpoint — controls, tests, documents, people. # Publish your integration Source: https://developer.vanta.com/docs/guides/list-your-integration Submit your finished integration for review and publish it to the Vanta marketplace. Once your public integration is built and tested, the final step is getting it listed in the [Vanta marketplace](https://app.vanta.com/integrations) so customers can discover and install it. ## Before you submit Make sure you have: * A working public integration created via the [Build an Integration](/docs/quickstart/build-integration) quickstart. * Successfully completed an end-to-end OAuth flow with a test customer account. * Sent at least one resource type or document into Vanta from your integration. * Marketing assets ready: logo (SVG), short description, long description, and a setup guide URL. ## Submission checklist In the [Developer Console](https://app.vanta.com/settings/developer-console), confirm your application name, description, category, and installation URL match what you want customers to see in the marketplace. Email [integrationpartners@vanta.com](mailto:integrationpartners@vanta.com) with your logo, short and long descriptions, and a link to your customer-facing setup documentation, and ask for a marketplace review. Vanta will validate the OAuth flow, the resources you push, and your customer setup guide. Once approved, Vanta enables your listing and notifies you. Customers can then find and install your integration directly from the marketplace. Need help? Reach out to [integrationpartners@vanta.com](mailto:integrationpartners@vanta.com) at any point in the listing process. # Offboard personnel Source: https://developer.vanta.com/docs/guides/offboard-people Complete the offboarding workflow for ex-employees — deactivating unmonitored accounts and recording an acknowledger — using the Manage Vanta API. This guide completes the offboarding workflow for departed employees using `POST /v1/people/offboard` on the Manage Vanta API — deactivating unmonitored accounts, recording an acknowledger, and marking each person's offboarding tasks complete. The build prompt below generates a daily job that drains the offboarding queue: it classifies every FORMER employee as already-complete, blocked, or eligible, then offboards the eligible ones in batches of up to 1000. ## Before you begin This guide is for Vanta admins managing data inside their own Vanta account. You'll need: * A Manage Vanta [API token](/docs/quickstart/manage-vanta). * The token must have scopes `vanta-api.all:read` and `vanta-api.all:write`. * For each person you're offboarding, all of the following must already be true: * Their employment `status` is `FORMER`. * All **monitored** accounts are deactivated (this is automatic when an integration reports the deactivation). * All **custom offboarding tasks** are complete. `POST /v1/people/offboard` will mark **unmonitored** accounts deactivated and complete the offboarding for you. It will **not** auto-complete custom offboarding tasks — those have to be done in the Vanta UI before this call will succeed. Wiring this into your HRIS? Run a daily job: query `GET /v1/people?employmentStatusMatchesAny=FORMER`, filter to people whose `tasksSummary.status` is not yet `OFFBOARDING_COMPLETE`, and call Step 3 in batches. **Your terminal** — call [`GET /v1/people`](/reference/manage-vanta/overview) and filter to `FORMER` employees so you only see candidates. Inspect each person's `tasksSummary.status` — anyone whose status is already `OFFBOARDING_COMPLETE` is done; anyone else with `status: FORMER` is a candidate. ```bash Terminal theme={"system"} curl 'https://api.vanta.com/v1/people?pageSize=50&employmentStatusMatchesAny=FORMER' \ -H 'Accept: application/json' \ -H 'Authorization: Bearer YOUR_TOKEN' ``` Response (truncated) ```json theme={"system"} { "results": { "data": [ { "id": "635c369a274dff2743f29160", "emailAddress": "former-employee@example.com", "name": { "display": "Adrian Test" }, "employment": { "status": "FORMER", "endDate": "2024-09-21T00:00:00.000Z" }, "tasksSummary": { "status": "OVERDUE" } } ] } } ``` Copy the `id` of each candidate — you'll send them in Step 3. Token is expired (one-hour lifetime), missing, or lacks `vanta-api.all:read`. Mint a fresh one — see [Authentication → Token expiration](/docs/concepts/authentication#token-expiration). That person is already offboarded. Skip them — calling `offboard` on them is a no-op. `POST /v1/people/offboard` will fail until those are completed. Finish them on the [Personnel page](https://app.vanta.com/people/people) (or via your HRIS workflow) before calling Step 3. **Your terminal** — every offboarding event records who acknowledged it (typically a security or HR admin). The `acknowledgerId` is **not** a Person `id` — it's the Vanta User Account ID of a `CURRENT` employee. Get it from either: * [`GET /v1/users`](/reference/manage-vanta/overview), or * the `userId` field on a person returned from [`GET /v1/people`](/reference/manage-vanta/overview). ```bash Terminal theme={"system"} curl 'https://api.vanta.com/v1/users?pageSize=10' \ -H 'Accept: application/json' \ -H 'Authorization: Bearer YOUR_TOKEN' ``` Copy the user `id` of the acknowledger you'll record on every entry. Most teams hard-code this to a specific compliance lead's user ID. Yes. Offboarding fails if the `acknowledgerId` belongs to a `FORMER` employee. `acknowledgerId` refers to the Vanta User Account ID, not the Person ID. Pull it from `GET /v1/users` or from the `userId` field on the corresponding person record. **Your terminal** — `POST /v1/people/offboard` with an `updates` array. Each entry needs the person `id` and the `acknowledgerId` you picked. ```javascript Node.js theme={"system"} const ACKNOWLEDGER_ID = "5df91759d463fd48218e9f15"; const res = await fetch("https://api.vanta.com/v1/people/offboard", { method: "POST", headers: { "Content-Type": "application/json", Authorization: "Bearer YOUR_TOKEN", }, body: JSON.stringify({ updates: [ { id: "635c369a274dff2743f29160", acknowledgerId: ACKNOWLEDGER_ID }, { id: "65a0caf8b4c7501f891e2183", acknowledgerId: ACKNOWLEDGER_ID }, ], }), }); console.log(await res.json()); ``` ```python Python theme={"system"} import requests ACKNOWLEDGER_ID = "5df91759d463fd48218e9f15" ids = ["635c369a274dff2743f29160", "65a0caf8b4c7501f891e2183"] r = requests.post( "https://api.vanta.com/v1/people/offboard", headers={"Authorization": "Bearer YOUR_TOKEN"}, json={ "updates": [ {"id": person_id, "acknowledgerId": ACKNOWLEDGER_ID} for person_id in ids ] }, ) r.raise_for_status() print(r.json()) ``` ```bash Terminal theme={"system"} curl -X POST 'https://api.vanta.com/v1/people/offboard' \ -H 'Content-Type: application/json' \ -H 'Accept: application/json' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -d '{ "updates": [ { "id": "635c369a274dff2743f29160", "acknowledgerId": "5df91759d463fd48218e9f15" }, { "id": "65a0caf8b4c7501f891e2183", "acknowledgerId": "5df91759d463fd48218e9f15" } ] }' ``` Expected response (`200`) — a per-person result so you can see which offboardings succeeded: ```json theme={"system"} { "results": [ { "id": "635c369a274dff2743f29160", "status": "SUCCESS" }, { "id": "65a0caf8b4c7501f891e2183", "status": "ERROR", "message": "Custom offboarding task incomplete" } ] } ``` Up to **1000** people per call. Successful entries are committed even if other entries return `ERROR` — fix and retry only the failures. The person still has open custom offboarding tasks or monitored accounts that haven't deactivated. Resolve those (typically by waiting for the next sync from your IDP/MDM) and retry just that `id`. Your token has `vanta-api.all:read` but not `vanta-api.all:write`. Mint a token with both scopes. Re-call [`GET /v1/people/{personId}`](/reference/manage-vanta/overview). The `tasksSummary.status` flips to `OFFBOARDING_COMPLETE` when the offboarding is recorded. **Reassigning their controls first?** Run [Assign a control owner](/docs/guides/add-an-owner-to-a-control) for everything they own before this call so nothing ends up orphaned to a `FORMER` user. ## Congratulations You've completed the offboarding workflow for one or more ex-employees. Their unmonitored accounts are now marked deactivated, an acknowledger is recorded for the audit log, and their `tasksSummary.status` is `OFFBOARDING_COMPLETE`. ## Next steps Reassign every control the offboarded person owned before they leave the system. Confirm the offboarded user no longer appears in your overdue-task report. Import the collection and run `offboard` against a sandbox in seconds. Browse every Manage Vanta endpoint — controls, tests, documents, people. # Find failing tests Source: https://developer.vanta.com/docs/guides/query-test-results-and-filter-for-failing-resources Find tests that need attention, then drill into the specific entities (users, buckets, repos, etc.) causing them to fail, using the Manage Vanta API. This guide builds a remediation report from Vanta — every `NEEDS_ATTENTION` test, drilled down to the specific failing entities (users, buckets, repos, devices, vulnerabilities) behind each one. It pairs `GET /v1/tests?statusFilter=NEEDS_ATTENTION` with `GET /v1/tests/{testId}/entities?entityStatus=FAILING` on the Manage Vanta API. Use the ask prompt for an MCP-driven snapshot, or the build prompt to emit NDJSON suitable for downstream ticketing or dashboards, complete with `newlyFailingEntities` and `fixedEntities` diffs across runs. ## Before you begin This guide is for Vanta admins managing data inside their own Vanta account. You'll need: * A Manage Vanta [API token](/docs/quickstart/manage-vanta). * The token must have scope `vanta-api.all:read`. Tests in Vanta are automated configuration checks — either pre-built when you connect an integration, or [Custom Tests](https://help.vanta.com/hc/en-us/articles/28012720726036-Creating-Custom-Tests) you author. Each failing test has one or more **entities** behind it: the specific S3 bucket, IAM user, repo, or person that's out of compliance. This guide finds failing tests, then resolves them down to those entities. Building a remediation dashboard? Cache the test list (refreshed every 6–12 hours) and only re-fetch entities for tests whose `status` is `NEEDS_ATTENTION` and whose `lastTestRunDate` has changed. **Your terminal** — call [`GET /v1/tests`](/reference/manage-vanta/overview) with `statusFilter=NEEDS_ATTENTION`. Add `categoryFilter` or `frameworkFilter` to narrow further. ```bash Terminal theme={"system"} curl 'https://api.vanta.com/v1/tests?pageSize=10&statusFilter=NEEDS_ATTENTION&categoryFilter=INFRASTRUCTURE' \ -H 'Accept: application/json' \ -H 'Authorization: Bearer YOUR_TOKEN' ``` Response (truncated) ```json theme={"system"} { "results": { "data": [ { "id": "inventory-list-owners", "name": "Inventory items have active owners", "lastTestRunDate": "2024-07-26T23:20:42.307Z", "status": "NEEDS_ATTENTION", "category": "Infrastructure", "remediationStatusInfo": { "status": "OVERDUE", "soonestRemediateByDate": "2023-09-20T15:12:00.092Z", "itemCount": 8 }, "owner": { "id": "64992d9c01bf8bd6638dfe40", "displayName": "Alex González" } } ], "pageInfo": { "hasNextPage": false, "endCursor": "..." } } } ``` Copy each `id` you want to inspect — you'll send it as the path parameter in Step 2. The test ID is human-readable (e.g. `inventory-list-owners`), and you can also copy it from the URL on the [Tests page](https://app.vanta.com/tests). Token is expired (one-hour lifetime), missing, or lacks `vanta-api.all:read`. Mint a fresh one — see [Authentication → Token expiration](/docs/concepts/authentication#token-expiration). `OK`, `NEEDS_ATTENTION` (failing), `IN_PROGRESS`, `DEACTIVATED`, `INVALID`, `NOT_APPLICABLE`. Most remediation tooling only cares about `NEEDS_ATTENTION`. Add `frameworkFilter=soc2` (or `iso27001`, `hipaa`, etc.) and/or `integrationFilter=aws`. Combine with `categoryFilter` to narrow to e.g. failing AWS infrastructure tests for SOC 2. **Your terminal** — call [`GET /v1/tests/{testId}/entities`](/reference/manage-vanta/overview) with `entityStatus=FAILING` (the default). Each entity is the specific resource — an AWS account, S3 bucket, IAM user, etc. — that's causing the test to fail. ```javascript Node.js theme={"system"} const TEST_ID = "inventory-list-owners"; const res = await fetch( `https://api.vanta.com/v1/tests/${TEST_ID}/entities?entityStatus=FAILING&pageSize=50`, { headers: { Authorization: "Bearer YOUR_TOKEN" }, }, ); const body = await res.json(); for (const entity of body.results.data) { console.log(entity.responseType, entity.displayName, entity.id); } ``` ```python Python theme={"system"} import requests TEST_ID = "inventory-list-owners" r = requests.get( f"https://api.vanta.com/v1/tests/{TEST_ID}/entities", headers={"Authorization": "Bearer YOUR_TOKEN"}, params={"entityStatus": "FAILING", "pageSize": 50}, ) r.raise_for_status() for entity in r.json()["results"]["data"]: print(entity["responseType"], entity["displayName"], entity["id"]) ``` ```bash Terminal theme={"system"} TEST_ID="inventory-list-owners" curl "https://api.vanta.com/v1/tests/$TEST_ID/entities?entityStatus=FAILING&pageSize=50" \ -H 'Accept: application/json' \ -H 'Authorization: Bearer YOUR_TOKEN' ``` Expected response (`200`): ```json theme={"system"} { "results": { "data": [ { "id": "65fc81a3359c8508c9af880f", "entityStatus": "FAILING", "displayName": "account-123456789012", "responseType": "AWS account", "lastUpdatedDate": "2024-06-18T20:17:38.463Z", "createdDate": "2024-06-18T20:17:38.463Z" } ], "pageInfo": { "hasNextPage": false, "endCursor": "..." } } } ``` `displayName` is what you'll surface in your UI ("S3 bucket `my-data-bucket` is failing"). `id` is the entity reference if you want to deactivate it later. The `testId` is wrong. They're case-sensitive and human-readable (e.g. `inventory-list-owners`, not `Inventory list owners`). Re-run Step 1 and copy the `id` exactly. Pagination — `pageSize` defaults to 10. Pass `pageSize=50` (max 100) and paginate with `pageCursor` until `hasNextPage` is `false`. Some tests have hundreds of failing entities. Pass `entityStatus=DEACTIVATED` to see entities you've explicitly excluded from the test. These don't count toward failure but are still tracked. The entity payload identifies *what* is failing (`responseType` + `displayName` + `id`); the *why* lives on the parent test. Call [`GET /v1/tests/{testId}`](/reference/manage-vanta/overview) for the same `testId` and read: * `failureDescription` — what condition the entity is violating. * `remediationDescription` — the recommended fix. Pair those two fields with the entity's `responseType` and `displayName` to produce a full remediation item ("`AWS account account-123456789012` is failing because … — fix by …"). There is no per-entity evidence-download endpoint. Failing entities themselves are the evidence, and the fields above are the full remediation payload the API exposes. For source-system detail on the underlying resource (owner, tags, deep link into AWS/Okta/etc.), open the test on the [Tests page](https://app.vanta.com/tests) in the Vanta Dashboard. To mark a failing entity as a known false positive or accepted risk, deactivate it with a written justification. The reason is preserved on the entity for the audit trail. ```bash Terminal theme={"system"} curl -X POST "https://api.vanta.com/v1/tests/$TEST_ID/entities/$ENTITY_ID/deactivate" \ -H 'Content-Type: application/json' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -d '{ "deactivateReason": "Bastion host — exempted per ticket SEC-1234", "deactivateUntilDate": "2026-12-31T00:00:00Z" }' ``` `deactivateReason` is required; `deactivateUntilDate` is optional (omit it for an indefinite deactivation). Reactivate later with [`POST /v1/tests/{testId}/entities/{entityId}/reactivate`](/reference/manage-vanta/overview). The endpoint deactivates one entity per call — there is no bulk-justification endpoint for test entities. To justify many entities, loop over the failing entities from Step 2 and call deactivate per entity, staying under the [50 requests/minute Manage Vanta rate limit](/reference/manage-vanta/overview#rate-limits). For vulnerabilities, use [`POST /v1/vulnerabilities/deactivate`](/reference/manage-vanta/overview), which accepts a batch. **Suppressing a known false positive?** Use [`POST /v1/tests/{testId}/entities/{entityId}/deactivate`](/reference/manage-vanta/overview) with a reason. Reactivate later with the matching `/reactivate` endpoint. ## Congratulations You've gone from "which tests are failing?" to "which specific resources are causing each failure?" — exactly the slice you need to drive remediation, file tickets, or ping the right owner. ## Next steps Many "needs attention" infrastructure tests are because resources are missing owners or descriptions. Mark resources `inScope: false` to remove them from a test entirely. Import the collection and run the tests + entities calls against a sandbox in seconds. Browse every Manage Vanta endpoint — tests, entities, controls, documents, people. # Scope resources in or out Source: https://developer.vanta.com/docs/guides/scope-resources-at-the-integration-level Control which resources synced from a connected integration are tested and used as compliance evidence, using the Manage Vanta API. This guide flips resources synced from a connected integration in or out of scope using `PATCH /v1/integrations/{integrationId}/resource-kinds/{resourceKind}/resources` on the Manage Vanta API. Out-of-scope resources stay visible in the inventory but stop counting as compliance evidence and stop running through tests. The build prompt below generates a scheduled job that applies regex-based scoping rules — like "exclude every `dev-*` GCP project" — in batches of 50. ## Before you begin This guide is for Vanta admins managing data inside their own Vanta account. You'll need: * A Manage Vanta [API token](/docs/quickstart/manage-vanta). * The token must have scopes `vanta-api.all:read` and `vanta-api.all:write`. * At least one connected integration whose resources you want to scope. Vanta-built integrations pull in resources — user accounts, cloud instances, code repositories, and more — that get tested for compliance. Marking a resource `inScope: false` excludes it from those tests entirely. Use it for sandbox accounts, test instances, or systems explicitly outside your audit boundary. Want to know which resources are scopable before you write code? `GET /v1/integrations/{integrationId}/resource-kinds/{resourceKind}` returns `isScopable: true|false` along with `numResources` / `numInScope` counters. **Your terminal** — pick the `integrationId` and `resourceKind` you're targeting, then list resources with the filters you care about. Common choices: `isInScope=true` to find things to scope **out**, or `isInScope=false` to bring something back **in**. ```bash Terminal theme={"system"} curl 'https://api.vanta.com/v1/integrations/gcp/resource-kinds/GCPComputeInstance/resources?connectionId=663e78b85360cc947add64bd&isInScope=true&pageSize=50' \ -H 'Accept: application/json' \ -H 'Authorization: Bearer YOUR_TOKEN' ``` Response (truncated) ```json theme={"system"} { "results": { "data": [ { "responseType": "ComputeInstance", "resourceKind": "GCPComputeInstance", "resourceId": "663e78bb5360cc947addd5f3", "connectionId": "663e78b85360cc947add64bd", "displayName": "vm-backend-service-2", "owner": "61a66a98538a952a6533f540", "inScope": true, "description": "GCP Compute Instance", "account": "amalgamated-widgets-demo", "region": "us-central1-a" } ], "pageInfo": { "hasNextPage": false, "endCursor": "..." } } } ``` Copy each `resourceId` you want to update — you'll send them in Step 2. Token is expired (one-hour lifetime), missing, or lacks `vanta-api.all:read`. Mint a fresh one — see [Authentication → Token expiration](/docs/concepts/authentication#token-expiration). Call [`GET /v1/integrations`](/reference/manage-vanta/overview) to list connected integrations, their `connectionIds`, and the `resourceKinds` they expose (e.g. `aws`, `gcp`, `okta`, `snowflake`). Pass `connectionId=` to filter to a single connection (e.g. one of two GCP projects). Without it, the response covers every connection for that integration. Some resource kinds (e.g. policy compliance results) can't be scoped out — `isScopable` will be `false` on the resource-kind details. Trying to update those will return an error. **Your terminal** — `PATCH /v1/integrations/{integrationId}/resource-kinds/{resourceKind}/resources` with an `updates` array. Each entry is keyed by `id` (the `resourceId`) and may set `inScope`, `ownerId`, and/or `description`. ```javascript Node.js theme={"system"} const INTEGRATION_ID = "gcp"; const RESOURCE_KIND = "GCPComputeInstance"; const res = await fetch( `https://api.vanta.com/v1/integrations/${INTEGRATION_ID}/resource-kinds/${RESOURCE_KIND}/resources`, { method: "PATCH", headers: { "Content-Type": "application/json", Authorization: "Bearer YOUR_TOKEN", }, body: JSON.stringify({ updates: [ { id: "663e78bb5360cc947addd5f3", inScope: false }, { id: "663e78bb5360cc947addd611", inScope: false }, ], }), }, ); console.log(await res.json()); ``` ```python Python theme={"system"} import requests INTEGRATION_ID = "gcp" RESOURCE_KIND = "GCPComputeInstance" r = requests.patch( f"https://api.vanta.com/v1/integrations/{INTEGRATION_ID}/resource-kinds/{RESOURCE_KIND}/resources", headers={"Authorization": "Bearer YOUR_TOKEN"}, json={ "updates": [ {"id": "663e78bb5360cc947addd5f3", "inScope": False}, {"id": "663e78bb5360cc947addd611", "inScope": False}, ] }, ) r.raise_for_status() print(r.json()) ``` ```bash Terminal theme={"system"} curl -X PATCH 'https://api.vanta.com/v1/integrations/gcp/resource-kinds/GCPComputeInstance/resources' \ -H 'Content-Type: application/json' \ -H 'Accept: application/json' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -d '{ "updates": [ { "id": "663e78bb5360cc947addd5f3", "inScope": false }, { "id": "663e78bb5360cc947addd611", "inScope": false } ] }' ``` Expected response (`200`) — a per-resource result so you can tell which entries failed: ```json theme={"system"} { "results": [ { "id": "663e78bb5360cc947addd5f3", "status": "SUCCESS" }, { "id": "663e78bb5360cc947addd611", "status": "SUCCESS" } ] } ``` The bulk endpoint accepts up to **50** resources per call. Page through Step 1 and call this endpoint in batches if you have more. The `message` field tells you which entry failed and why — typically because the `id` doesn't belong to that `(integrationId, resourceKind)` or the resource kind isn't scopable. Successful entries are still applied; only fix and retry the failures. The `integrationId` or `resourceKind` is wrong. They're case-sensitive — `gcp` and `GCPComputeInstance` are different fields. Re-run Step 1 to confirm the exact spellings. Your token has `vanta-api.all:read` but not `vanta-api.all:write`. Mint a token with both scopes. **Updating one resource at a time?** Use `PATCH /v1/integrations/{integrationId}/resource-kinds/{resourceKind}/resources/{resourceId}` with `{ "inScope": false }`. It returns `204 No Content` on success and is the right call when you're reacting to a single event (e.g. a webhook from your tagging system). ## Congratulations You've taken control of which resources Vanta tests against. Out-of-scope resources are skipped by automated tests and won't show up as failing entities, while staying visible in your inventory for traceability. The change is captured in your audit log. ## Next steps For everything that **stays** in scope, ensure each resource has an active owner and description. Confirm a previously-failing test no longer flags the resource you scoped out. Import the collection and run the bulk PATCH against a sandbox in seconds. Browse every Manage Vanta endpoint — integrations, resources, controls, tests, documents. # Upload a document Source: https://developer.vanta.com/docs/guides/upload-a-document Attach an evidence file to a Vanta document and submit it for review, using the Manage Vanta API. This guide attaches an evidence file to a Vanta document with `POST /v1/documents/{documentId}/uploads` and submits it for review with `POST /v1/documents/{documentId}/submit` on the Manage Vanta API. The build prompt below generates a scheduled job that watches a local directory of evidence files named `.`, uploads each matching file as multipart/form-data, and flips the document to `OK` — idempotent across runs using local file mtime. ## Before you begin This guide is for Vanta admins managing data inside their own Vanta account. You'll need: * A Manage Vanta [API token](/docs/quickstart/manage-vanta). * The token must have scopes `vanta-api.all:read`, `vanta-api.all:write`, `vanta-api.documents:upload`. * The evidence file you want to upload (PDF, image, etc.) saved locally. Re-uploading evidence on a recurring schedule (e.g. quarterly access reviews)? Wire this flow into a cron job or CI step using the same three calls below. **Your terminal** — call [`GET /v1/documents`](/reference/manage-vanta/overview) and pick the document you want to attach a file to. ```bash Terminal theme={"system"} curl 'https://api.vanta.com/v1/documents?pageSize=100&frameworkMatchesAny=soc2' \ -H 'Accept: application/json' \ -H 'Authorization: Bearer YOUR_TOKEN' ``` Response ```json theme={"system"} { "results": { "data": [ { "id": "access-requests", "title": "Access request ticket and history", "category": "Account setup", "overallStatus": "Needs document", "url": "https://app.vanta.com/documents/access-requests" } ], "pageInfo": { "hasNextPage": true, "endCursor": "..." } } } ``` Copy the `id` field — you'll send it as the path parameter in the next step. Token is expired (one-hour lifetime), missing, or lacks `vanta-api.all:read`. Mint a fresh one — see [Authentication → Token expiration](/docs/concepts/authentication#token-expiration). Filter the response client-side by `title` or `category`, paginate with `pageCursor` if `hasNextPage` is `true`, or copy the ID directly from the [Documents page](https://app.vanta.com/documents) URL. Add `statusMatchesAny=Needs%20document` (or `Needs%20update`) to narrow the response to documents that still require an upload. **Your terminal** — `POST /v1/documents/{documentId}/uploads` as `multipart/form-data` with the file in the `file` field. ```javascript Node.js theme={"system"} import fs from "node:fs"; const DOCUMENT_ID = "YOUR_DOCUMENT_ID"; // id from Step 1 const FILE_PATH = "./access-requests.pdf"; const form = new FormData(); form.append( "file", new Blob([fs.readFileSync(FILE_PATH)], { type: "application/pdf" }), "access-requests.pdf", ); form.append("description", "Q3 access review evidence"); const res = await fetch( `https://api.vanta.com/v1/documents/${DOCUMENT_ID}/uploads`, { method: "POST", headers: { Authorization: "Bearer YOUR_TOKEN" }, body: form, }, ); console.log(await res.json()); ``` ```python Python theme={"system"} import requests DOCUMENT_ID = "YOUR_DOCUMENT_ID" # id from Step 1 FILE_PATH = "./access-requests.pdf" with open(FILE_PATH, "rb") as f: r = requests.post( f"https://api.vanta.com/v1/documents/{DOCUMENT_ID}/uploads", headers={"Authorization": "Bearer YOUR_TOKEN"}, files={"file": ("access-requests.pdf", f, "application/pdf")}, data={"description": "Q3 access review evidence"}, ) r.raise_for_status() print(r.json()) ``` ```bash Terminal theme={"system"} DOCUMENT_ID="YOUR_DOCUMENT_ID" # id from Step 1 curl -X POST "https://api.vanta.com/v1/documents/$DOCUMENT_ID/uploads" \ -H 'Accept: application/json' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -F 'file=@"./access-requests.pdf"' \ -F 'description="Q3 access review evidence"' ``` Expected response (`200`) — the uploaded file metadata: ```json theme={"system"} { "id": "66a935ff0dfddd9e7c568558", "creationDate": "2024-07-30T18:50:39.419Z", "updatedDate": "2024-07-30T18:50:39.419Z", "deletionDate": null, "description": "Q3 access review evidence", "effectiveDate": "2024-07-30T18:50:39.177Z", "fileName": "access-requests.pdf", "title": "Manual Evidence", "mimeType": "application/pdf", "url": "https://app.vanta.com/acme/doc/Manual%20Evidence-5l14b5mljzt50h3uoo82sk", "uploadedByUserId": null } ``` The upload lands in a **draft** state. It won't satisfy the document until you submit it in Step 3. The document ID is wrong. Re-run Step 1 and copy `id` exactly — IDs may be human-readable (e.g. `access-requests`) or a 24-character ObjectId (e.g. `6596e2a8f62c73fb64960581`). The request must be `multipart/form-data` — don't set `Content-Type` manually, let your HTTP client add the boundary. Pass the file with `-F` (curl), `files=` (requests), or a `FormData` body (fetch). Your token is missing `vanta-api.documents:upload`. This is a separate scope from `vanta-api.all:write` — uploads require it explicitly. Mint a new token that includes all three scopes (`vanta-api.all:read`, `vanta-api.all:write`, `vanta-api.documents:upload`). **Your terminal** — `POST /v1/documents/{documentId}/submit` to move the document from `draft` to `OK`. Until you do this, auditors won't see the new evidence. ```javascript Node.js theme={"system"} const DOCUMENT_ID = "YOUR_DOCUMENT_ID"; // id from Step 1 const res = await fetch( `https://api.vanta.com/v1/documents/${DOCUMENT_ID}/submit`, { method: "POST", headers: { Authorization: "Bearer YOUR_TOKEN" }, }, ); console.log(res.status); ``` ```python Python theme={"system"} import requests DOCUMENT_ID = "YOUR_DOCUMENT_ID" # id from Step 1 r = requests.post( f"https://api.vanta.com/v1/documents/{DOCUMENT_ID}/submit", headers={"Authorization": "Bearer YOUR_TOKEN"}, ) r.raise_for_status() print(r.status_code) ``` ```bash Terminal theme={"system"} DOCUMENT_ID="YOUR_DOCUMENT_ID" # id from Step 1 curl -X POST "https://api.vanta.com/v1/documents/$DOCUMENT_ID/submit" \ -H 'Accept: application/json' \ -H 'Authorization: Bearer YOUR_TOKEN' ``` A `200` response means the document's `overallStatus` has flipped to `OK` and the upload is visible to auditors. Same root cause as Step 2 — re-check the `documentId` you copied from Step 1. The document has no draft uploads to submit. Re-run Step 2, then submit. You can also confirm the upload exists with `GET /v1/documents/{documentId}/uploads`. **Replacing stale evidence?** Repeat Step 2 with the new file, then Step 3 — the latest submitted upload becomes the canonical evidence for the document. ## Congratulations You've attached an evidence file to a Vanta document and submitted it for review. The document's status is now `OK`, the upload is captured in your audit log, and auditors can pull the file directly from Vanta. ## Next steps Make a specific user accountable for the controls this document supports. React in real time when document status or uploads change. Import the collection and run `uploads` + `submit` against a sandbox in seconds. Browse every Manage Vanta endpoint — controls, tests, documents, people. # Set custom fields on vendors Source: https://developer.vanta.com/docs/guides/use-custom-fields-with-vendors Attach organization-specific metadata — contract dates, internal owners, risk tiers, anything you track — to vendors when creating or updating them, using the Manage Vanta API. This guide writes organization-specific metadata — contract dates, internal owners, risk tiers, ticket links — to vendors using `PATCH /v1/vendors/{vendorId}` with a `customFields` payload on the Manage Vanta API. Custom field labels must be defined in the Vanta vendor settings UI first; the API only fills in their values. The build prompt below generates a scheduled job that syncs a CSV export from a procurement or GRC system into Vanta, only PATCHing vendors whose fields actually changed. ## Before you begin This guide is for Vanta admins managing data inside their own Vanta account. You'll need: * A Manage Vanta [API token](/docs/quickstart/manage-vanta). * The token must have scopes `vanta-api.all:read` and `vanta-api.all:write`. * The custom fields you want to set must be defined ahead of time in the Vanta UI (the API can only **fill** custom fields, not create them). Custom fields let you attach organization-specific metadata to vendors — contract end dates, internal owners, risk ratings, or anything else you track. They're defined in the [Vendor settings page](https://app.vanta.com/vendors) by name and type, then set or updated via the API. Importing a backlog of vendors from your procurement system? Define every custom field you'll send first in the [Vendor settings page](https://app.vanta.com/vendors), then run Step 1 in a loop. Field names sent in the API must match the Vanta-side `label` exactly — including case, and values must match the field's type: * `String` → JSON string: `"value": "Tier 1"` * `Number` → JSON number: `"value": 10` * `Date` → ISO 8601 string: `"value": "2026-01-01T00:00:00.000Z"` * `Boolean` → JSON bool: `"value": true` **Your terminal** — `POST /v1/vendors` with a `customFields` array. Each entry has `label` (matches the Vanta-side field name) and `value` (matches the field's type). ```javascript Node.js theme={"system"} const res = await fetch("https://api.vanta.com/v1/vendors", { method: "POST", headers: { "Content-Type": "application/json", Authorization: "Bearer YOUR_TOKEN", }, body: JSON.stringify({ name: "Acme Corp", websiteUrl: "https://acmecorp.com", category: "cloudStorage", customFields: [ { label: "contractEndDate", value: "2026-01-01T00:00:00.000Z" }, { label: "internalRiskTier", value: "Tier 2" }, ], }), }); const vendor = await res.json(); console.log(vendor.id); ``` ```python Python theme={"system"} import requests r = requests.post( "https://api.vanta.com/v1/vendors", headers={"Authorization": "Bearer YOUR_TOKEN"}, json={ "name": "Acme Corp", "websiteUrl": "https://acmecorp.com", "category": "cloudStorage", "customFields": [ {"label": "contractEndDate", "value": "2026-01-01T00:00:00.000Z"}, {"label": "internalRiskTier", "value": "Tier 2"}, ], }, ) r.raise_for_status() print(r.json()["id"]) ``` ```bash Terminal theme={"system"} curl -X POST 'https://api.vanta.com/v1/vendors' \ -H 'Content-Type: application/json' \ -H 'Accept: application/json' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -d '{ "name": "Acme Corp", "websiteUrl": "https://acmecorp.com", "category": "cloudStorage", "customFields": [ { "label": "contractEndDate", "value": "2026-01-01T00:00:00.000Z" }, { "label": "internalRiskTier", "value": "Tier 2" } ] }' ``` Expected response (`200`) — the full vendor object, including the values you just set: ```json theme={"system"} { "id": "a2f7e1b9d0c3f4e5a6c7b8d8", "name": "Acme Corp", "category": { "displayName": "cloudStorage" }, "customFields": [ { "label": "contractEndDate", "value": "2026-01-01T00:00:00.000Z" }, { "label": "internalRiskTier", "value": "Tier 2" } ] } ``` The `label` doesn't match a defined custom field. Check the [Vendor settings page](https://app.vanta.com/vendors) — labels are case-sensitive and must match exactly. Your JSON value doesn't match the custom field's type. A `Date` field needs an ISO 8601 string; a `Number` needs a JSON number, not a string; a `Boolean` needs `true`/`false`, not `"true"`/`"false"`. **Your terminal** — `PATCH /v1/vendors/{vendorId}` with the same `customFields` shape. Only the fields you send are changed; omitted fields keep their current values. ```javascript Node.js theme={"system"} const VENDOR_ID = "YOUR_VENDOR_ID"; const res = await fetch(`https://api.vanta.com/v1/vendors/${VENDOR_ID}`, { method: "PATCH", headers: { "Content-Type": "application/json", Authorization: "Bearer YOUR_TOKEN", }, body: JSON.stringify({ customFields: [ { label: "contractEndDate", value: "2027-01-01T00:00:00.000Z" }, ], }), }); console.log(await res.json()); ``` ```python Python theme={"system"} import requests VENDOR_ID = "YOUR_VENDOR_ID" r = requests.patch( f"https://api.vanta.com/v1/vendors/{VENDOR_ID}", headers={"Authorization": "Bearer YOUR_TOKEN"}, json={ "customFields": [ {"label": "contractEndDate", "value": "2027-01-01T00:00:00.000Z"}, ] }, ) r.raise_for_status() print(r.json()) ``` ```bash Terminal theme={"system"} VENDOR_ID="YOUR_VENDOR_ID" curl -X PATCH "https://api.vanta.com/v1/vendors/$VENDOR_ID" \ -H 'Content-Type: application/json' \ -H 'Accept: application/json' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -d '{ "customFields": [ { "label": "contractEndDate", "value": "2027-01-01T00:00:00.000Z" } ] }' ``` A `200` response returns the updated vendor with its new `customFields`. Sending `customFields` with `category` in the same call wipes any category-derived risk attributes before applying your custom values — see the [Create a vendor guide](/docs/guides/create-vendors-and-attach-documentation) for the ordering rules. The `vendorId` is wrong. Re-run [`GET /v1/vendors`](/reference/manage-vanta/overview) and copy the `id` exactly, or grab it from the URL on the [Vendor page](https://app.vanta.com/vendors). Send the field with `value: null`. The label still has to match a defined field. **Bulk-syncing from a procurement system?** List vendors with `GET /v1/vendors`, match each one to your source-of-truth record by `name` or `websiteUrl`, then run Step 2 per vendor with the latest custom-field values. Tokens expire hourly — re-mint at the top of each run. ## Congratulations You've populated organization-specific metadata on your vendors. Custom field values are visible on each vendor's profile, queryable via the API, and included in vendor exports for auditors. ## Next steps Set up a new vendor end-to-end with metadata, custom fields, and a SOC 2 report. Make a specific user accountable for vendor-management controls. Import the collection and run vendor `POST` and `PATCH` against a sandbox in seconds. Browse every Manage Vanta endpoint — vendors, controls, tests, documents, people. # Find vulnerabilities approaching SLAs Source: https://developer.vanta.com/docs/guides/vulnerabilities-with-approaching-slas Query vulnerabilities approaching their remediation deadline so you can prioritize fixes before they breach SLA, using the Manage Vanta API. This guide queries `GET /v1/vulnerabilities` on the Manage Vanta API for CRITICAL and HIGH vulnerabilities whose remediation SLA deadline falls inside a configurable window — the standard pattern is "next 14 days" so security teams can prioritize fixes before they breach. Use the ask prompt to surface them through the Vanta MCP server, or the build prompt to generate a scheduled job that groups results by integration and skips suppressed vulnerabilities. ## Before you begin This guide is for Vanta admins managing data inside their own Vanta account. You'll need: * A Manage Vanta [API token](/docs/quickstart/manage-vanta). * The token must have scope `vanta-api.all:read`. * At least one vulnerability scanner integration connected to Vanta (e.g. Snyk, Qualys, Inspector). Vanta consolidates scan results from multiple tools into a single view and tracks remediation against the SLAs you've configured. The vulnerabilities endpoint lets you slice that view by SLA window so you can act on what's actually about to breach. Wiring this into a daily nudge or ticketing automation? Re-mint your token at the top of each run, query `slaDeadlineBeforeDate` set to "today + 14 days", and feed the response into your downstream system. Decide which vulnerabilities to surface. Most teams use one of: * **Approaching breach** — `slaDeadlineAfterDate` = now, `slaDeadlineBeforeDate` = now + 7–14 days. * **Already breached** — `slaDeadlineBeforeDate` = now (with no `slaDeadlineAfterDate`). * **All vulnerabilities with an SLA** — both params omitted, but `includeVulnerabilitiesWithoutSlas=false`. Layer in `severity=CRITICAL` (or `HIGH`), `isFixAvailable=true`, and `integrationId=` to narrow further. ```bash Terminal theme={"system"} # Two-week window: due after today, before today + 14 days AFTER=$(date -u +"%Y-%m-%dT%H:%M:%SZ") BEFORE=$(date -u -v+14d +"%Y-%m-%dT%H:%M:%SZ") # GNU date: date -u -d '+14 days' +%Y-%m-%dT%H:%M:%SZ echo "from $AFTER to $BEFORE" ``` `severity` (`CRITICAL`/`HIGH`/`MEDIUM`/`LOW`), `isFixAvailable`, `integrationId`, `packageIdentifier`, `vulnerableAssetId`, `externalVulnerabilityId`, `q` (free-text search), and `includeVulnerabilitiesWithoutSlas`. By default the endpoint excludes vulnerabilities that have no `remediateByDate`. Set `includeVulnerabilitiesWithoutSlas=true` to include them — useful if a scanner doesn't emit severities Vanta can map to an SLA. **Your terminal** — call [`GET /v1/vulnerabilities`](/api-reference/vulnerabilities/get-vulnerabilities) with the SLA window and any extra filters. ```javascript Node.js theme={"system"} const after = new Date().toISOString(); const before = new Date(Date.now() + 14 * 24 * 60 * 60 * 1000).toISOString(); const url = new URL("https://api.vanta.com/v1/vulnerabilities"); url.searchParams.set("pageSize", "50"); url.searchParams.set("slaDeadlineAfterDate", after); url.searchParams.set("slaDeadlineBeforeDate", before); url.searchParams.set("severity", "CRITICAL"); url.searchParams.set("isFixAvailable", "true"); const res = await fetch(url, { headers: { Authorization: "Bearer YOUR_TOKEN" }, }); const body = await res.json(); for (const vuln of body.results.data) { console.log(vuln.severity, vuln.name, "due", vuln.remediateByDate); } ``` ```python Python theme={"system"} from datetime import datetime, timedelta, timezone import requests after = datetime.now(timezone.utc).isoformat().replace("+00:00", "Z") before = (datetime.now(timezone.utc) + timedelta(days=14)).isoformat().replace("+00:00", "Z") r = requests.get( "https://api.vanta.com/v1/vulnerabilities", headers={"Authorization": "Bearer YOUR_TOKEN"}, params={ "pageSize": 50, "slaDeadlineAfterDate": after, "slaDeadlineBeforeDate": before, "severity": "CRITICAL", "isFixAvailable": "true", }, ) r.raise_for_status() for vuln in r.json()["results"]["data"]: print(vuln["severity"], vuln["name"], "due", vuln["remediateByDate"]) ``` ```bash Terminal theme={"system"} AFTER=$(date -u +"%Y-%m-%dT%H:%M:%SZ") BEFORE=$(date -u -v+14d +"%Y-%m-%dT%H:%M:%SZ") curl --get 'https://api.vanta.com/v1/vulnerabilities' \ --data-urlencode 'pageSize=50' \ --data-urlencode "slaDeadlineAfterDate=$AFTER" \ --data-urlencode "slaDeadlineBeforeDate=$BEFORE" \ --data-urlencode 'severity=CRITICAL' \ --data-urlencode 'isFixAvailable=true' \ -H 'Accept: application/json' \ -H 'Authorization: Bearer YOUR_TOKEN' ``` Expected response (`200`) — paginated vulnerabilities, sorted by `remediateByDate` ascending (most urgent first): ```json theme={"system"} { "results": { "data": [ { "id": "65f05b5def4a9f04c44e5748", "name": "CVE-2021-3711", "description": "Alpine Linux Security Update for OpenSSL", "integrationId": "qualys", "packageIdentifier": "libssl1.1:1.1.1g-r0", "vulnerabilityType": "COMMON", "targetId": "65f05b57f37f4ffbd87dc20c", "severity": "CRITICAL", "cvssSeverityScore": 9.8, "isFixable": true, "fixedVersion": "1.1.1n-r0", "remediateByDate": "2024-04-16T17:14:26.718Z", "externalURL": "https://qualysguard.qg4.apps.qualys.com/cs/#/...", "deactivateMetadata": null } ], "pageInfo": { "hasNextPage": true, "endCursor": "..." } } } ``` Use `targetId` to join back to the affected asset, `externalURL` to deep-link to your scanner, and `remediateByDate` to drive your countdown. Token is expired (one-hour lifetime), missing, or lacks `vanta-api.all:read`. Mint a fresh one — see [Authentication → Token expiration](/docs/concepts/authentication#token-expiration). `slaDeadlineAfterDate` and `slaDeadlineBeforeDate` must be ISO 8601 timestamps with timezone (e.g. `2024-04-16T17:14:26.718Z`). Plain dates without time-of-day will be rejected. Read `results.pageInfo.endCursor` and `hasNextPage`. Re-call with `pageCursor=` until `hasNextPage` is `false`. Don't try to fetch all vulnerabilities in one call — `pageSize` caps at 100. That vulnerability has been deactivated (suppressed). It still appears in the list but won't impact tests. Filter client-side on `deactivateMetadata == null` if you only want active items. **Suppressing a known false positive?** Use [`POST /v1/vulnerabilities/deactivate`](/api-reference/vulnerabilities/deactivate-vulnerability-monitoring-for-a-vulnerability) with a reason. Reactivate later with the matching `/reactivate` endpoint. ## Congratulations You've pulled the canonical list of vulnerabilities approaching their SLA deadline. Wire this into a Slack channel, Jira ticket creator, or PagerDuty schedule so your remediation work happens against actual deadlines instead of a static dashboard. *** ## Next steps See which tests are failing because of overdue vulnerabilities. React in real time when a vulnerability is detected, deactivated, or remediated. Import the collection and run the vulnerability query against a sandbox in seconds. Browse every Manage Vanta endpoint — vulnerabilities, tests, controls, documents, people. # Postman setup Source: https://developer.vanta.com/docs/postman-setup Import the Vanta Postman collections and start testing requests in minutes. The Vanta Postman collections cover every public API endpoint, paired with a shared environment for authentication and base URLs. Each API ships as its own collection, so you can download only what you need. ## Downloads Download a collection for each API you plan to use. Shared variables for authentication and base URLs. Used by every collection below. Manage your Vanta tenant: tests, controls, vendors, people, and more. Push resources from your platform into Vanta. Run an audit programmatically using the Conduct an Audit endpoints. ## Setup Download Postman from the [official site](https://www.postman.com/downloads/) if you don't have it already. 1. Open Postman and click **Import** in the upper-left corner. 2. Drag in (or select) the environment file and at least one collection from the downloads above. 3. Click **Import** to add them to your workspace. You can import additional collections later — they'll all share the same environment. Go to **Environments** in the left nav and select **Vanta Environment**. The following variables are available: | Variable | Description | | - | - | | `baseUrl` | Preset to `https://api.vanta.com/v1` — the Vanta base URL (`https://api.vanta.com`) with the `/v1` path pre-prefixed so endpoints can be dropped in directly. Vanta Gov tenants should change this to `https://api.vanta-gov.com/v1`. | | `authUrl` | Preset to `https://api.vanta.com/oauth/token` — used to fetch an access token. | | `clientId` | Your application's client ID. | | `clientSecret` | Your application's client secret. | | `bearerToken` | Set automatically after running **Create Token** — no manual entry needed. | Don't have a `clientId` or `clientSecret` yet? Follow the [Manage Vanta quickstart](/docs/quickstart/manage-vanta) to create an application. Run the **Create Token** request from any imported collection. A post-response script stores the token in `bearerToken`, so subsequent requests across every collection are authenticated for you. Create Token request ## Build Integrations variables If you imported the **Build Integrations** collection, the environment includes additional variables for resource IDs. Populate these using the [resource creation](/docs/concepts/resources) flow. Build Integrations variables ## Next steps Full walkthrough of OAuth authentication. Try every endpoint directly from the docs. # Build a public integration Source: https://developer.vanta.com/docs/quickstart/build-integration Become a Vanta partner, complete the OAuth authorization-code flow, and push your first resource into a customer's Vanta tenant. 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](/docs/guides/become-partner). * 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](/docs/quickstart/build-private-integration) instead. **Custom resources and Custom Tests are not available to public integrations.** Public integrations push [built-in resource types](/reference/build-integrations/overview) (`UserAccount`, `Computer`, `Vulnerability`, `BackgroundCheck`, `TrainingRecord`, etc.) into customer tenants, and Vanta runs its [built-in tests](/docs/concepts/tests#built-in-tests-vs-custom-tests) against them automatically. Both [custom resources](/docs/concepts/resources#custom-resources) and [Custom Tests](/docs/concepts/tests#custom-tests) are private-integration features, available only to direct Vanta customers building against their own tenant. Partners cannot push custom resources or author Custom Tests on a customer's behalf, and there is no Build Integrations API for either. **Vanta Dashboard** — sign in to the 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](https://app.vanta.com/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. **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`. From **your server**, redirect the user's browser to `/oauth/authorize` on **the customer's regional Vanta app host** — this host is regional even though the API host (`api.vanta.com`) isn't: | Region | App host | | - | - | | United States | `https://app.vanta.com` | | Europe | `https://app.eu.vanta.com` | | Australia | `https://app.aus.vanta.com` | Sending an EU or AU customer to `app.vanta.com` instead of their own region's host can break authorization. A complete authorization URL (US example) looks like: ```text theme={"system"} 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: | Parameter | Description | | - | - | | `client_id` | From the Developer Console. | | `scope` | Space-separated list of scopes (see below). | | `state` | An 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_uri` | Must match a redirect URI registered in Step 2. | | `source_id` | Unique 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_type` | Always `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: | Code | Cause | | - | - | | 1 | The initial redirect to Vanta is missing required query parameters. | | 2 | Invalid scopes. | | 3 | Invalid `responseType` (must be `code`). | | 4 | Error loading the registered application. | | 5 | Application not found — check `client_id`. | | 6 | `redirect_uri` is not registered in the Developer Console. | 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. ```bash Terminal theme={"system"} 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" }' ``` ```javascript Node.js theme={"system"} const response = await fetch("https://api.vanta.com/oauth/token", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ client_id: process.env.VANTA_CLIENT_ID, client_secret: process.env.VANTA_CLIENT_SECRET, code, source_id: accountId, redirect_uri: "https://partner-app.com/oauth/callback", grant_type: "authorization_code", }), }); const tokens = await response.json(); ``` ```python Python theme={"system"} import requests response = requests.post( "https://api.vanta.com/oauth/token", json={ "client_id": client_id, "client_secret": client_secret, "code": code, "source_id": account_id, "redirect_uri": "https://partner-app.com/oauth/callback", "grant_type": "authorization_code", }, ) tokens = response.json() ``` Expected response: ```json theme={"system"} { "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`. 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: ```bash Terminal theme={"system"} 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" } ] }' ``` ```javascript Node.js theme={"system"} const response = await fetch( "https://api.vanta.com/v1/resources/user_account", { method: "PUT", headers: { Authorization: `Bearer ${access_token}`, "Content-Type": "application/json", }, body: JSON.stringify({ 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", }, ], }), } ); ``` ```python Python theme={"system"} import requests response = requests.put( "https://api.vanta.com/v1/resources/user_account", headers={ "Authorization": f"Bearer {access_token}", "Content-Type": "application/json", }, json={ "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`): ```json theme={"system"} { "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 [built-in tests](/docs/concepts/tests#built-in-tests-vs-custom-tests) for that resource in the customer's tenant. There's nothing to wire up. [Custom resources](/docs/concepts/resources#custom-resources) and [Custom Tests](/docs/concepts/tests#custom-tests) are **not available to public integrations**. Both are a private-integration feature that customers use inside their own tenant. 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](/reference/build-integrations/overview). 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. 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. ```bash Terminal theme={"system"} 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" }' ``` ```javascript Node.js theme={"system"} await fetch("https://api.vanta.com/v1/oauth/token/suspend", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ token: tokenToRevoke, client_id: process.env.VANTA_CLIENT_ID, client_secret: process.env.VANTA_CLIENT_SECRET, }), }); ``` ```python Python theme={"system"} import requests requests.post( "https://api.vanta.com/v1/oauth/token/suspend", json={ "token": token_to_revoke, "client_id": client_id, "client_secret": client_secret, }, ) ``` Expected response (`200 OK` — idempotent; same response if the token is already revoked): ```json theme={"system"} {} ``` 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. ```json theme={"system"} { "message": "Token does not belong to this application", "statusCode": 401 } ``` From your **terminal**, read back the resource you pushed in Step 5 to confirm the full flow — auth, write, and read — is wired correctly. ```bash Terminal theme={"system"} 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](https://app.vanta.com/access/accounts)** — the user you `PUT` should appear with the same `displayName` and `email`, and your integration should be listed under **Settings → Integrations**. | Scenario | Test input | Expected result | | - | - | - | | Success | Valid `access_token` after the PUT in Step 5 | `200 OK`, response `data` includes `user_123`; the user appears in the customer's Vanta dashboard | | Auth failure | Expired or revoked `access_token` | `401 Unauthorized` — refresh per Step 4 and retry | | Edge case | Refresh-token rotation: exchange `refresh_token` for a new pair, then repeat the GET with the new `access_token` | `200 OK`, same `data` — confirms rotation works without re-authorization | | Edge case | A `uniqueId` you previously pushed but omitted from the latest `PUT` | The 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 Submit your integration for review and publish to the Vanta marketplace. Full reference of every resource type Vanta accepts out of the box. Deep dive on the resource lifecycle, including custom resources. Every endpoint available to Build Integrations apps. # Build a custom integration for compliance data Source: https://developer.vanta.com/docs/quickstart/build-private-integration Push user accounts and custom resources from a homegrown app into Vanta, then turn that data into pass/fail evidence with a Custom Test. By the end of this quickstart you'll have a private integration that pushes user accounts and custom resources into your Vanta tenant, with a Custom Test turning that data into pass/fail compliance evidence. ## Before you begin Make sure you have: * A Vanta account with admin access. * A terminal or HTTP client (cURL, Postman, or your language of choice). Building an integration for multiple Vanta organizations? Private integrations are single-tenant and use the simpler `client_credentials` grant. If you want other Vanta organizations to install your integration, follow the [Build a Public Integration quickstart](/docs/quickstart/build-integration) instead. **Vanta Dashboard** — sign in to the Vanta app, open [Settings → Developer Console](https://app.vanta.com/settings/developer-console), and click **Create**. Choose **Build Integrations** as the app type, then select **Private** for the distribution. Fill in: * **Application name** — `Demo Private Integration` (or enter a name of your choosing). * **Application description** — `Vanta quickstart demo integration` Vanta Developer Console showing the Build Integrations app creation form with Private distribution selected The OAuth `client_id` is auto-generated. Click **Generate client secret** to create the secret. Store both values securely. You can rotate the secret at any time without invalidating data you've already pushed. From your **terminal**, exchange your client credentials for an access token. This quickstart requests two scopes: `connectors.self:write-resource` to push data and `connectors.self:read-resource` to read it back for verification. ```bash Terminal theme={"system"} curl --location 'https://api.vanta.com/oauth/token' \ --header 'Content-Type: application/json' \ --data '{ "client_id": "your_client_id", "client_secret": "your_client_secret", "scope": "connectors.self:write-resource connectors.self:read-resource", "grant_type": "client_credentials" }' ``` ```javascript Node.js theme={"system"} const response = await fetch("https://api.vanta.com/oauth/token", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ client_id: "your_client_id", client_secret: "your_client_secret", scope: "connectors.self:write-resource connectors.self:read-resource", grant_type: "client_credentials", }), }); const { access_token } = await response.json(); ``` ```python Python theme={"system"} import requests response = requests.post( "https://api.vanta.com/oauth/token", json={ "client_id": "your_client_id", "client_secret": "your_client_secret", "scope": "connectors.self:write-resource connectors.self:read-resource", "grant_type": "client_credentials", }, ) access_token = response.json()["access_token"] ``` Expected response: ```json theme={"system"} { "access_token": "vat_your_token", "expires_in": 3600, "token_type": "Bearer" } ``` **One token at a time.** Vanta only allows one active access token per application — requesting a new token immediately revokes the previous one. Tokens expire after one hour, so most integrations request a fresh token at the top of each sync run. 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. You requested a scope that isn't available to **Build Integrations** apps. Private integrations can request `connectors.self:write-resource`, `connectors.self:read-resource`, `self:write-document`, and `self:read-document`. Request only what your tool needs. Most private integrations start with `UserAccount` — Vanta's representation of a person in an external system, used for access reviews. `PUT` is idempotent on `uniqueId`, so it's safe to retry on network errors. 1. **Vanta Dashboard** — in your private app's **Resources** tab, click **Add resource**, choose the **User Account** base type, save, and copy the generated `Resource ID`. Every `PUT` references this ID so Vanta knows which resource configuration the records belong to. Resources tab in the Vanta app showing the Add resource flow with the User Account base type selected 2. **Terminal** — replace `your_token_here` with the `access_token` from Step 2 and `your_resource_id` with the `Resource ID` you just copied, then push a record: ```bash Terminal theme={"system"} curl --request PUT 'https://api.vanta.com/v1/resources/user_account' \ --header 'Authorization: Bearer your_token_here' \ --header 'Content-Type: application/json' \ --data '{ "resourceId": "your_resource_id", "resources": [ { "uniqueId": "user_123", "displayName": "Jane Doe", "fullName": "Jane Doe", "accountName": "jane.doe", "email": "developers@vanta.com", "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" } ] }' ``` ```javascript Node.js theme={"system"} const response = await fetch( "https://api.vanta.com/v1/resources/user_account", { method: "PUT", headers: { Authorization: `Bearer ${access_token}`, "Content-Type": "application/json", }, body: JSON.stringify({ resourceId: "your_resource_id", 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", }, ], }), } ); ``` ```python Python theme={"system"} import requests response = requests.put( "https://api.vanta.com/v1/resources/user_account", headers={ "Authorization": f"Bearer {access_token}", "Content-Type": "application/json", }, json={ "resourceId": "your_resource_id", "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`): ```json theme={"system"} { "results": { "accepted": 1, "rejected": 0 } } ``` Each `PUT` represents the **full state** of resources you own. 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. Your access token has expired (tokens last one hour) or your app wasn't granted the `connectors.self:write-resource` scope. Re-run Step 2 with the scopes shown above. Use a **custom resource** to define your own schema and push data Vanta doesn't model out of the box — homegrown app objects, on-prem servers, internal review records, and the like. 1. **Vanta Dashboard** — open your private app's **Resources** tab and create a new resource using the **Custom Resource** base type. Give it a name (e.g. `Internal Server`) and define the custom fields you want to sync to Vanta using JSON Type Definition. ```json theme={"system"} { "properties": { "name": { "type": "string" }, "active": { "type": "boolean" }, "memory": { "type": "int32" }, "lastUpdated": { "type": "timestamp" } } } ``` Save and copy the generated `Resource ID` — you'll reference it on every push. 2. **Terminal** — push records to the custom-resource endpoint. Replace `your_token_here` with your `access_token` and `your_custom_resource_id` with the `Resource ID` you just copied. Each record includes the base fields (`displayName`, `uniqueId`, `externalUrl`) at the top level and your schema fields nested inside `customProperties`. ```bash Terminal theme={"system"} curl --request PUT 'https://api.vanta.com/v1/resources/custom_resource' \ --header 'Authorization: Bearer your_token_here' \ --header 'Content-Type: application/json' \ --data '{ "resourceId": "your_custom_resource_id", "resources": [ { "displayName": "auth-prod-1", "uniqueId": "srv_001", "externalUrl": "https://app.example.com/servers/srv_001", "customProperties": { "name": "auth-prod-1", "active": true, "memory": 16384, "lastUpdated": "2026-05-05T00:00:00Z" } } ] }' ``` ```javascript Node.js theme={"system"} const response = await fetch( "https://api.vanta.com/v1/resources/custom_resource", { method: "PUT", headers: { Authorization: `Bearer ${access_token}`, "Content-Type": "application/json", }, body: JSON.stringify({ resourceId: "your_custom_resource_id", resources: [ { displayName: "auth-prod-1", uniqueId: "srv_001", externalUrl: "https://app.example.com/servers/srv_001", customProperties: { name: "auth-prod-1", active: true, memory: 16384, lastUpdated: "2026-05-05T00:00:00Z", }, }, ], }), } ); ``` ```python Python theme={"system"} import requests response = requests.put( "https://api.vanta.com/v1/resources/custom_resource", headers={ "Authorization": f"Bearer {access_token}", "Content-Type": "application/json", }, json={ "resourceId": "your_custom_resource_id", "resources": [ { "displayName": "auth-prod-1", "uniqueId": "srv_001", "externalUrl": "https://app.example.com/servers/srv_001", "customProperties": { "name": "auth-prod-1", "active": True, "memory": 16384, "lastUpdated": "2026-05-05T00:00:00Z", }, } ], }, ) ``` Custom resources don't have built-in compliance tests — Vanta doesn't know what "compliant" means for your schema yet. Step 5 walks through authoring a Custom Test to define that pass/fail logic. The `resourceId` in your `PUT` body must match the ID Vanta generated when you created the custom resource in the Dashboard. Open the resource definition in the **Resources** tab and copy the ID exactly — it's case-sensitive. The custom resource from Step 4 is now syncing data, but Vanta doesn't yet know what "compliant" means for your schema — until you author a Custom Test, the records won't contribute to any framework. Custom Tests are authored in the Vanta Dashboard; there is no API to create them. Custom Tests may require a plan upgrade or add-on. See [Vanta Plans and Pricing](https://www.vanta.com/pricing) or contact your Customer Success team if the **+ Create custom test** button isn't visible on the Tests page. 1. **Vanta Dashboard** — open the Vanta app, navigate to the **Tests** page, and click **+ Create custom test**. 2. Fill in the test metadata: * **Test name** — e.g. `Internal servers have ≥ 8 GiB RAM and are active`. * **Description** — what the test verifies, in business terms (this is what auditors read). * **How to fix / remediate** — instructions for whoever owns a failing resource. * **Integration** — select the private integration you created in Step 1. The resource picker will then show every resource type that app syncs, including the custom resource from Step 4. 3. **Pick the resource type** — choose the custom resource you defined in Step 4 (e.g. `Internal Server`). 4. Use the logic builder to define the **pass/fail rule** for each record. Define the resource outcome as follows: ```text theme={"system"} active equals true AND memory >= 8192 ``` Each record you `PUT` is evaluated against this rule independently. If any record fails, the test fails for that resource and contributes to your framework gap. Custom Test builder in the Vanta app showing the resource picker, pass/fail logic, and evaluation preview 5. Review the **evaluation preview**. Vanta runs the test against the records you've already synced and shows pass/fail counts plus a per-resource breakdown. If nothing appears, confirm Step 4's `PUT` returned `accepted: 1` (or higher). 6. Click **Create** to save the test. 7. Finalize the test so it counts toward your compliance program: * **Map it to controls.** Open the test, go to the **Controls** tab, click **Add control**, and select the controls (and therefore frameworks) the test should satisfy. * **Assign an SLA category** so failing resources have a remediation deadline. * **Assign a test owner** so failures route to the right person. **Custom Tests are immutable after creation.** If you need to change the logic, name, or description later, copy the test and edit the copy — Vanta keeps the original for audit trail purposes. Lock in your rule before mapping to controls. The Custom Test builder only shows resource types that have at least one record synced. Re-run the `PUT` from Step 4 to push at least one record, then refresh the **+ Create custom test** flow. If it still doesn't appear, confirm you selected the correct integration (Step 1's private app) — custom resources are scoped per-app. Either no records have been synced yet, or your scoping conditions filter them all out. Remove scoping conditions temporarily to confirm records exist, then re-add them one at a time to find the offending filter. Custom Test logic is evaluated **per record**. By default, every record must pass for the test to pass (one failing record fails the whole test), but the reducer is configurable when you author the test — confirm you picked the one you intended. Open the per-resource breakdown in the test view to see which records are flagged and why. From your **terminal**, read back the resource you pushed in Step 3 to confirm you completed everything correctly. ```bash Terminal theme={"system"} curl 'https://api.vanta.com/v1/resources/user_account?resourceId=your_resource_id&pageSize=10' \ --header 'Authorization: Bearer your_token_here' \ --header 'Accept: application/json' ``` Then open the Vanta app: * Navigate to the **[Access page](https://app.vanta.com/access/accounts)**. The user you `PUT` should appear with the same `displayName` and `email`. * Open **Tests → Custom**, find the test you authored in Step 5, and confirm it shows the pass/fail outcome you expected for each record. | Scenario | Test input | Expected result | | - | - | - | | Success | Valid `access_token` after the PUT in Step 3 | `200 OK`, response `data` includes `user_123`; the user appears in the Vanta dashboard | | Custom Test success | Custom resource records pushed in Step 4 that satisfy the rule from Step 5 | Test result page shows **Passing** with each record listed under "Passing resources" | | Auth failure | Expired `access_token` (older than one hour) | `401 Unauthorized` — re-run Step 2 for a fresh token | | Edge case | A `uniqueId` you previously pushed but omitted from the latest `PUT` | The resource is marked as no longer existing in Vanta and disappears from the Custom Test's evaluated set — confirms the full-state replacement model from Step 3 | ## Congratulations You have a working private integration — authenticating with `client_credentials`, pushing both built-in and custom resources into your own Vanta tenant, and evaluating that data against compliance criteria you define via Custom Tests. From here you can: * **Schedule it.** Run the sync hourly from cron, a Lambda, or your CI runner. Always request a fresh token at the start of the run. * **Expand resource coverage.** Push additional supported types (`Computer`, `Vulnerability`, `BackgroundCheck`, `TrainingRecord`, etc.) from the same app. * **Add more Custom Tests.** Layer additional pass/fail rules on the same custom resource, or copy an existing test to create a variant for a different scope. * **Map tests to frameworks.** Wire each Custom Test to the controls it satisfies so failing resources surface as gaps in SOC 2, ISO 27001, HIPAA, and any other framework you're tracking. ## Next steps Full reference of every resource type Vanta accepts out of the box. Deep dive on defining a custom schema and pushing records. Turn the data you sync into compliance evidence with pass/fail logic. Every endpoint available to Build Integrations apps. # Pull Information Request Lists for your audits Source: https://developer.vanta.com/docs/quickstart/conduct-audit Get a list of Information Request Lists (IRLs) for the audits assigned to your firm. By the end of this quickstart you'll have a working auditor access token and you'll have used it to list the information requests for one of your active audits. ## Before you begin Make sure you have: * An active **Vanta Audit Partner** registration. If you don't see the **Auditor API** option in your Vanta navigation, contact your Vanta representative. * An auditor account in Vanta. * At least one active audit assigned to your firm — most endpoints return data only for audits that already exist. * A terminal or HTTP client (cURL, Postman, or your language of choice). This quickstart is for **Vanta audit partners** pulling data from their customers' audits. If you're a Vanta customer automating your own tenant, see the [Manage Vanta quickstart](/docs/quickstart/manage-vanta). If you're a partner building a public integration, see the [Build an Integration quickstart](/docs/quickstart/build-integration). **Vanta Dashboard** — sign in to the Vanta app with your auditor email. In the left navigation, open **Auditor API**, then click **Create**. Vanta Auditor API page with the Create button highlighted Give your application a name and description, then click **Create**. Auditor application creation form with name and description fields The OAuth `client_id` is auto-generated. Click **Generate client secret** to create the secret. Store both values securely — only share with trusted team members. You can rotate the secret at any time. Auditor application detail page showing the generated client_id and Generate client secret button From your **terminal**, exchange your client credentials for an access token. This quickstart only makes read calls, so request the minimum scope: `auditor-api.audit:read`. ```bash Terminal theme={"system"} curl --location 'https://api.vanta.com/oauth/token' \ --header 'Content-Type: application/json' \ --data '{ "client_id": "your_client_id", "client_secret": "your_client_secret", "scope": "auditor-api.audit:read", "grant_type": "client_credentials" }' ``` ```javascript Node.js theme={"system"} const response = await fetch("https://api.vanta.com/oauth/token", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ client_id: "your_client_id", client_secret: "your_client_secret", scope: "auditor-api.audit:read", grant_type: "client_credentials", }), }); const { access_token } = await response.json(); ``` ```python Python theme={"system"} import requests response = requests.post( "https://api.vanta.com/oauth/token", json={ "client_id": "your_client_id", "client_secret": "your_client_secret", "scope": "auditor-api.audit:read", "grant_type": "client_credentials", }, ) access_token = response.json()["access_token"] ``` Expected response: ```json theme={"system"} { "access_token": "vat_your_token", "expires_in": 3600, "token_type": "Bearer" } ``` **One token at a time.** Vanta only allows one active access token per application — requesting a new token immediately revokes the previous one. Tokens expire after one hour. Double-check the `client_id` and `client_secret` from the Auditor API page. 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. You requested a scope that isn't available to **Auditor** apps. For this quickstart, request only `auditor-api.audit:read`. Auditor apps can also request `auditor-api.audit:write`, `auditor-api.auditor:read`, and `auditor-api.auditor:write` — request only what your tool needs. From your **terminal**, call `GET /v1/audits` to see the audits assigned to your firm, then grab an `auditId` to use in the next step. Pass `isActiveAudit=true` to filter out audits with a final report already uploaded. Replace `your_token_here` with the `access_token` from Step 2. ```bash Terminal theme={"system"} curl --location 'https://api.vanta.com/v1/audits?isActiveAudit=true&pageSize=10' \ --header 'Accept: application/json' \ --header 'Authorization: Bearer your_token_here' ``` ```javascript Node.js theme={"system"} const response = await fetch( "https://api.vanta.com/v1/audits?isActiveAudit=true&pageSize=10", { headers: { Accept: "application/json", Authorization: `Bearer ${access_token}`, }, } ); const { results } = await response.json(); const auditId = results.data[0].id; ``` ```python Python theme={"system"} import requests response = requests.get( "https://api.vanta.com/v1/audits", params={"isActiveAudit": "true", "pageSize": 10}, headers={ "Accept": "application/json", "Authorization": f"Bearer {access_token}", }, ) audit_id = response.json()["results"]["data"][0]["id"] ``` Expected response — note the `id` field on each audit; that's the `auditId` you'll use in the next step: ```json theme={"system"} { "results": { "data": [ { "id": "65fc81a3359c8508c9af880f", "customerOrganizationName": "corporation.com", "customerDisplayName": "Corporation Company", "customerOrganizationId": "65fc81a3359c8508c9af880f", "auditStartDate": "2024-03-07T21:25:56.000Z", "auditEndDate": "2024-03-14T21:25:56.000Z", "framework": "SOC 2 Type II", "displayName": "Q1 2024 SOC 2 Audit", "auditFocus": "EXTERNAL" } ], "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", "endCursor": "YXJyYXljb25uZWN0aW9uOjE=" } } } ``` Either your firm has no active audits in flight, or every audit already has a final report uploaded (filtered out by `isActiveAudit=true`). Re-run the request without `isActiveAudit=true` to include completed audits. From your **terminal**, call `GET /v1/audits/{auditId}/information-requests` with the `auditId` from Step 3. This returns every information request (IR) on the audit — the evidence requirements your team and the customer are working through. Reuse the same `access_token` from Step 2 by replacing `your_token_here`. ```bash Terminal theme={"system"} curl --location 'https://api.vanta.com/v1/audits/65fc81a3359c8508c9af880f/information-requests?pageSize=10' \ --header 'Accept: application/json' \ --header 'Authorization: Bearer your_token_here' ``` ```javascript Node.js theme={"system"} const response = await fetch( `https://api.vanta.com/v1/audits/${auditId}/information-requests?pageSize=10`, { headers: { Accept: "application/json", Authorization: `Bearer ${access_token}`, }, } ); const { results } = await response.json(); console.log(`${results.data.length} information requests for ${auditId}`); ``` ```python Python theme={"system"} import requests response = requests.get( f"https://api.vanta.com/v1/audits/{audit_id}/information-requests", params={"pageSize": 10}, headers={ "Accept": "application/json", "Authorization": f"Bearer {access_token}", }, ) requests_list = response.json()["results"]["data"] print(f"{len(requests_list)} information requests for {audit_id}") ``` Expected response: ```json theme={"system"} { "results": { "data": [ { "id": "6890e473dce1da5d8406f5e7", "uniqueId": "1466132", "title": "Terminated Customer Deletion Evidence", "description": "Provide the data deletion evidence for a sample of terminated customers", "approvalStatus": "NEEDS_EVIDENCE", "cadence": "ANNUALLY", "frameworkCodes": ["SOC2_CC6.1"], "requestType": "SAMPLE", "dueDate": "2025-10-28T00:00:00.000Z", "ownerAssignment": { "type": "user", "id": "507f1f77bcf86cd799439011", "displayName": "John Doe" }, "creationDate": "2025-08-01T12:34:56.000Z", "modificationDate": "2025-08-02T08:00:00.000Z", "deletionDate": null } ], "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": "Njg5MGU0NzNkY2UxZGE1Z", "endCursor": "Njg5MGU0NzNkY2UxZGE1Z" } } } ``` Either the audit has no information requests yet, or the requests haven't been shared with the customer. Confirm in the Vanta dashboard that the audit has IRs configured. Note that this endpoint always includes soft-deleted records — check `deletionDate` to skip them. Your firm isn't assigned to this audit, or your application's allowlisted auditor emails don't include you. Re-run Step 3 and copy an `auditId` from the response — that list is already scoped to audits your firm can see. Pick an information request from the response and open the audit in the Vanta app — find the IR by its `uniqueId` or `title`. You should land on the same record the API just returned. Confirm on the dashboard: * The **title**, **description**, and **due date** match what the API returned. * The **approval status** matches `approvalStatus` from the response (e.g. `NEEDS_EVIDENCE`, `AWAITING_REVIEW`, `APPROVED`). * The **owner** matches `ownerAssignment.displayName`. | Scenario | Test input | Expected result | | - | - | - | | Success | An IR with `approvalStatus: "NEEDS_EVIDENCE"` from the response | The IR exists in the dashboard with matching title, description, and due date; status reads "Needs evidence" | | Auth failure | Expired `access_token` (older than one hour) | `401 Unauthorized` — re-run Step 2 for a fresh token | | Edge case | An IR with a non-null `deletionDate` | Record is soft-deleted; it won't appear in the dashboard, and your tool should skip or archive it | ## Congratulations You have a working auditor token and you've used it to read information requests from one of your active audits. From here you can: * **Pull the controls** for an audit with `GET /v1/audits/{auditId}/controls` to see every requirement in scope. * **Pull evidence** with `GET /v1/audits/{auditId}/evidence` to feed the customer's evidence into your audit-management tooling. * **Create custom IRs** with `POST /v1/audits/{auditId}/information-requests` to add evidence requirements that supplement Vanta's built-in scaffolding (requires the `auditor-api.audit:write` scope). * **Accept or flag evidence** on an IR programmatically once your team has reviewed it. ## Next steps Pull every control in scope for an audit, with framework codes and status. Create custom IRs, accept or flag evidence, and share the IR list with the customer. Every endpoint available to auditor apps. Import the Vanta collection and start testing requests in seconds. # Make your first API call to Vanta Source: https://developer.vanta.com/docs/quickstart/manage-vanta Get an access token and use it to list documents, policies, and evidence in your Vanta tenant, filtered by compliance framework. By the end of this quickstart you'll have a working access token and you'll have used it to list the documents stored in your Vanta instance, filtered by compliance framework. ## Before you begin Make sure you have: * A Vanta account with admin access. * A terminal or HTTP client (cURL, Postman, or your language of choice). This quickstart is for **security engineers and admins** automating their own Vanta account. If you're a partner building a public integration, see the [Build an Integration quickstart](/docs/quickstart/build-integration). If you're a Vanta audit partner, see the [Conduct an Audit quickstart](/docs/quickstart/conduct-audit). **Vanta Dashboard** — sign in to Vanta, open [Settings → Developer Console](https://app.vanta.com/settings/developer-console), and click **Create**. Choose **Manage Vanta** as the app type, then fill in: * **Application name** — `Demo Manage Vanta App` (or enter a name of your choosing). * **Application description** — `Vanta quickstart demo app` Vanta Developer Console showing the Create application form with app type, name, and description fields The OAuth `client_id` is auto-generated. Click **Generate client secret** to create the secret. Store both values securely. You can rotate the secret at any time. From your **terminal**, exchange your client credentials for an access token. This quickstart only makes read calls, so request the minimum scope: `vanta-api.all:read`. ```bash Terminal theme={"system"} curl --location 'https://api.vanta.com/oauth/token' \ --header 'Content-Type: application/json' \ --data '{ "client_id": "your_client_id", "client_secret": "your_client_secret", "scope": "vanta-api.all:read", "grant_type": "client_credentials" }' ``` ```javascript Node.js theme={"system"} const response = await fetch("https://api.vanta.com/oauth/token", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ client_id: "your_client_id", client_secret: "your_client_secret", scope: "vanta-api.all:read", grant_type: "client_credentials", }), }); const { access_token } = await response.json(); ``` ```python Python theme={"system"} import requests response = requests.post( "https://api.vanta.com/oauth/token", json={ "client_id": "your_client_id", "client_secret": "your_client_secret", "scope": "vanta-api.all:read", "grant_type": "client_credentials", }, ) access_token = response.json()["access_token"] ``` Expected response: ```json theme={"system"} { "access_token": "vat_your_token", "expires_in": 3600, "token_type": "Bearer" } ``` **One token at a time.** Vanta only allows one active access token per application — requesting a new token immediately revokes the previous one. Tokens expire after one hour. 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. You requested a scope that isn't available to **Manage Vanta** apps. For this quickstart, request only `vanta-api.all:read`. From your **terminal**, call `GET /v1/frameworks` to see which compliance frameworks are active in your Vanta instance, and grab a `frameworkId` to use in the next step. Replace `your_token_here` with the `access_token` from Step 2. ```bash Terminal theme={"system"} curl --location 'https://api.vanta.com/v1/frameworks?pageSize=10' \ --header 'Accept: application/json' \ --header 'Authorization: Bearer your_token_here' ``` ```javascript Node.js theme={"system"} const response = await fetch( "https://api.vanta.com/v1/frameworks?pageSize=10", { headers: { Accept: "application/json", Authorization: `Bearer ${access_token}`, }, } ); const { results } = await response.json(); const frameworkId = results.data[0].id; ``` ```python Python theme={"system"} import requests response = requests.get( "https://api.vanta.com/v1/frameworks", params={"pageSize": 10}, headers={ "Accept": "application/json", "Authorization": f"Bearer {access_token}", }, ) framework_id = response.json()["results"]["data"][0]["id"] ``` Expected response — note the `id` field on each framework (e.g. `soc2`, `iso27001_2022`): ```json theme={"system"} { "results": { "data": [ { "id": "soc2", "displayName": "SOC 2", "shorthandName": "SOC 2", "description": "AICPA standardized framework...", "numControlsCompleted": 43, "numControlsTotal": 86, "numDocumentsPassing": 7, "numDocumentsTotal": 16, "numTestsPassing": 21, "numTestsTotal": 46 } ], "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": "c29jMg==", "endCursor": "c29jMg==" } } } ``` From your **terminal**, call `GET /v1/documents` and filter by the `frameworkId` you just got with the `frameworkMatchesAny` query parameter. Reuse the `access_token` from Step 2. ```bash Terminal theme={"system"} curl --location 'https://api.vanta.com/v1/documents?frameworkMatchesAny=soc2&pageSize=10' \ --header 'Accept: application/json' \ --header 'Authorization: Bearer your_token_here' ``` ```javascript Node.js theme={"system"} const response = await fetch( `https://api.vanta.com/v1/documents?frameworkMatchesAny=${frameworkId}&pageSize=10`, { headers: { Accept: "application/json", Authorization: `Bearer ${access_token}`, }, } ); const { results } = await response.json(); console.log(`${results.data.length} documents for ${frameworkId}`); ``` ```python Python theme={"system"} import requests response = requests.get( "https://api.vanta.com/v1/documents", params={"frameworkMatchesAny": framework_id, "pageSize": 10}, headers={ "Accept": "application/json", "Authorization": f"Bearer {access_token}", }, ) documents = response.json()["results"]["data"] print(f"{len(documents)} documents for {framework_id}") ``` Expected response: ```json theme={"system"} { "results": { "data": [ { "id": "access-requests", "ownerId": "2", "category": "Account setup", "description": "Provide two examples of a recent access request and approval", "isSensitive": false, "title": "Access request ticket and history", "uploadStatus": "Needs document", "uploadStatusDate": "2024-03-17T00:00:00.000Z", "url": "https://example.com" } ], "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": "YWNjZXNzLXJlcXVlc3Rz", "endCursor": "YWNjZXNzLXJlcXVlc3Rz" } } } ``` Either the framework has no documents yet, or the `frameworkId` doesn't match a framework in your instance. Re-run Step 3 and copy the `id` exactly — it's case-sensitive (e.g. `soc2`, not `SOC2`). Pick a document from the response, copy its `url` field, and open it in your browser. The `url` is a deep link to that document's page in the Vanta dashboard, so you'll land on the same record the API just returned to you. Confirm that on the dashboard page: * The **title**, **category**, and **document** match what the API returned. * Open or download the document and verify it's the file your team expected to see for this evidence request. | Scenario | Test input | Expected result | | - | - | - | | Success | A document with `uploadStatus: "OK"` from the response | `url` opens the document page in Vanta; `title` / `category` match; the attached file matches what was uploaded | | Common failure | Expired `access_token` (older than one hour) | API returns `401 Unauthorized` — re-run Step 2 for a fresh token | | Edge case | A document with `uploadStatus: "Needs document"` | `url` opens the document page, but no file is attached yet — expected when no evidence has been uploaded for this requirement | ## Congratulations You have a working Manage Vanta token and you've used it to read documents out of your Vanta instance. From here you can: * **Create a document** with `POST /v1/documents` to track new evidence. * **Filter further** by combining `frameworkMatchesAny` with `statusMatchesAny` to find documents that need attention. * **Upload evidence** to an existing document via the document upload endpoint (requires the `vanta-api.documents:upload` scope). ## Next steps Use the same token to add a new document to your Vanta instance. Attach a file to an existing document in three steps. Every endpoint available to Manage Vanta apps. Import the Vanta collection and start testing requests in seconds. # Remediate a failing test with the Vanta MCP Source: https://developer.vanta.com/docs/quickstart/remediate-with-mcp Connect Claude Code, Codex, Cursor, or Perplexity to the Vanta MCP server, surface failing tests, and generate a remediation plan for one. Connect an AI tool to the [Vanta MCP server](/docs/vanta-mcp), list your failing compliance tests, and ask it to generate a remediation plan with a suggested code change. With the **Claude Code Vanta plugin**, you can take it further and open a draft pull request with the fix if you use infrastructure as code (IaC). ## Before you begin * A Vanta account with admin access. * One of: [Claude Code](https://claude.ai/download), [Cursor](https://cursor.com/download), [Codex](https://developers.openai.com/codex) (Desktop or CLI), or [Perplexity](https://www.perplexity.ai/). * At least one Vanta integration connected. Ideally, connect a **Cloud Provider** (AWS, GCP, or Azure) for failing resources and a **Version Control** integration (GitHub, GitLab, or Bitbucket) for the IaC that manages them. Vanta hosts a separate MCP server per region. Use the URL that matches your instance: | Region | MCP URL | | - | - | | United States | `https://mcp.vanta.com/mcp` | | Europe | `https://mcp.eu.vanta.com/mcp` | | Australia | `https://mcp.aus.vanta.com/mcp` | The examples below use the US URL. Swap in your region if needed. **Recommended:** Includes the MCP server, the `/vanta:list-tests` and `/vanta:fix-test` slash commands, and the PR-opening skill. In the **Claude Code CLI** (not claude.ai in a browser), run these in order. The marketplace must be registered before the plugin can install. ```bash theme={"system"} /plugin marketplace update anthropics/claude-plugins-official /plugin install vanta-mcp-plugin@claude-plugins-official /reload-plugins ``` **Type these commands** rather than pasting them. Claude Code treats a leading `/` in pasted text as a file-path trigger and can open a file picker instead of running the slash command. Then run `/mcp`, select **Vanta**, pick your region, and click **Allow** to finish OAuth. You skipped the first command. Run `/plugin marketplace update anthropics/claude-plugins-official` first, then re-run the install command. Confirm you're inside the Claude Code CLI (not a web chat window). `/plugin` and `/mcp` only work there. Run `/reload-plugins` again and wait a few seconds. If it still doesn't appear, re-run the install command. Open the authorization URL printed in the terminal yourself. If it's expired, run `/mcp → Vanta → Reconnect`. You get every MCP tool but no `/vanta:*` skills including PR generation. ```bash theme={"system"} claude mcp add --transport http vanta https://mcp.vanta.com/mcp ``` Then run `/mcp`, select **vanta**, and click **Allow**. You get every MCP tool but no `/vanta:*` skills including PR generation. 1. Open **Settings → Tools & MCP → Add custom MCP**. 2. Paste: ```json theme={"system"} { "mcpServers": { "vanta": { "url": "https://mcp.vanta.com/mcp" } } } ``` 3. Save, then click **Allow** when Cursor opens the OAuth flow. You get every MCP tool but no `/vanta:*` skills including PR generation. 1. **Settings → MCP servers → Add server**. 2. **Name:** `Vanta`, **Type:** **Streamable HTTP**, **URL:** `https://mcp.vanta.com/mcp`. 3. **Save**, then click **Authenticate** and **Allow**. You get every MCP tool but no `/vanta:*` skills including PR generation. Shares config with Codex Desktop. ```bash theme={"system"} codex mcp add vanta --url https://mcp.vanta.com/mcp codex mcp login vanta ``` Click **Allow** in the browser, then confirm with `codex mcp list`. You get every MCP tool but no `/vanta:*` skills including PR generation. 1. Add a **remote custom connector**. 2. URL: `https://mcp.vanta.com/mcp` (or your regional endpoint). 3. **Authentication: OAuth** → click **Allow**. Perplexity has no repository or shell access, so it usually returns a console-first plan and generic Terraform / CloudFormation snippets you can paste into a ticket. In your tool's chat, ask: ``` Show me the highest-priority failing Vanta tests relevant to this repository. ``` In the **Claude Code plugin**, you can run `/vanta:list-tests` instead. In **Perplexity** (no repo context), replace "relevant to this repository" with "ranked by severity". Optionally paste your stack ("we run on AWS + GitHub Actions") to bias results. ``` Found 12 failing tests. Top 5 for this repository: 1. GitHub repos should require pull request reviews before merging Test ID: github-repo-require-pr-reviews | Severity: HIGH 2. AWS S3 buckets should have server-side encryption enabled Test ID: aws-s3-bucket-server-side-encryption-enabled | Severity: HIGH 3. AWS IAM password policy should require minimum length of 14 Test ID: aws-iam-password-policy-minimum-length | Severity: MEDIUM ``` Pick a HIGH-severity test ID to use in the next step. Either everything's passing, or your OAuth token expired. Re-authorize: `/mcp → Vanta → Reconnect` (Claude Code), re-trigger OAuth in Cursor or Perplexity settings, click **Authenticate** in Codex Desktop, or run `codex mcp login vanta`. Re-open the right project before re-running the prompt. If your repo doesn't contain any IaC (or you're in Perplexity), the assistant falls back to severity ranking. Paste your stack to bias results. Ask which specific resources are failing the test you picked: ``` Show me which specific resources are failing the "TEST ID" test. ``` Replace `TEST ID` with the ID from Step 2. Example output for `github-repo-require-pr-reviews`: ``` 4 resources failing: • my-company/web-app — No branch protection rule on `main` • my-company/api-server — Branch protection does not require PR reviews • my-company/infra — Branch protection requires 0 reviewers • my-company/data-pipeline — No branch protection rule on `main` ``` You now know exactly what to fix. Check the integration field (GitHub org, AWS account ID, GCP project, etc.). If your company has multiple orgs or cloud accounts, focus on the one you own. Ask for the fix: ``` Generate a remediation plan for the "TEST ID" test. Include console steps, CLI commands, and a Terraform / CloudFormation / CDK snippet I can adapt. ``` In the **Claude Code plugin**, run `/vanta:fix-test TEST ID`. The plugin also scans your repo for matching IaC files and unlocks the optional PR step below. The assistant pulls the failing resources from Vanta and returns a multi-option plan. It typically includes a CLI command for the fastest fix, console steps for environments where the resource isn't managed by IaC, and an IaC snippet you can commit to prevent recurrence: ``` Failing resources (4): web-app, api-server, infra, data-pipeline Option A — gh CLI (fastest) gh api -X PUT repos/my-company/web-app/branches/main/protection \ -F required_pull_request_reviews.required_approving_review_count=1 \ -F enforce_admins=true \ -F required_status_checks=null \ -F restrictions=null (repeat for api-server, infra, data-pipeline) Option B — GitHub UI For each repo: Settings → Branches → Add branch protection rule → pattern `main` → "Require a pull request before merging" → approvals: 1. Option C — Terraform (prevents recurrence) resource "github_branch_protection" "web_app_main" { repository_id = github_repository.web_app.node_id pattern = "main" required_pull_request_reviews { required_approving_review_count = 1 } } Vanta will re-evaluate on its next sync (within 24 hours). ``` The assistant won't run CLI commands that mutate live resources on its own. It surfaces them and asks first. Pick the option that fits your environment and apply it. This step applies **only** if using the **Claude Code Vanta plugin**. This step assumes the failing resource is managed by IaC in a repo connected as a Vanta **Version Control** integration (GitHub, GitLab, or Bitbucket), the repo is open locally, and Claude has push access. If that's true, ask: ``` Open a draft pull request with the IaC changes from this plan. ``` The plugin matches your existing module structure, generates a minimal diff, and opens a draft PR against your current branch: ``` Opened draft PR #47: "fix: require PR reviews on 4 repos (Vanta github-repo-require-pr-reviews)" https://github.com/my-company/infra/pull/47 ``` Review the diff before marking it ready. Spot-check variable references and backend state. Stick with the plan from Step 4. Run the CLI, apply the UI steps, or hand it to the team that owns the resource. It searches `.tf` files in the root and common subfolders (`infra/`, `terraform/`, `ops/`). Point it elsewhere: *"The Terraform files are in `platform/infra/aws/`."* The resource probably lives in a different account, project, or repo. Use Step 4's CLI or UI option instead, or re-run from inside the repo that manages it. The plugin supports all three. Tell it which framework you use and it adjusts the diff. Once you've applied the fix (PR merged, CLI run, console steps done, or ticket handed off), ask: ``` What is the current status of the "TEST ID" test in Vanta? ``` Vanta re-evaluates tests on its next sync, usually within 24 hours. If it still shows as failing, wait for the next sync or trigger one from the Vanta dashboard. ## Congratulations You're connected to the Vanta MCP server and you've used it to surface failing tests, inspect failing resources, and generate a remediation plan. If you use the Claude Code plugin, you also opened an optional draft PR. From here: * **Remediate more tests.** Re-run Step 2 (or `/vanta:list-tests`) and repeat the flow. * **Explore other compliance data.** Ask your assistant about controls, vendors, vulnerabilities, or frameworks in plain English. * **Learn more about the MCP.** See the [Vanta MCP server reference](/docs/vanta-mcp). ## More things to try ``` Show me my SOC 2 controls, how many are complete versus in progress, and which controls have the most failing tests. ``` ``` List every CRITICAL vulnerability whose remediation deadline is in the next 30 days, and tell me which ones are already assigned. ``` ``` Which failing tests are mapped to both SOC 2 and ISO 27001? Show me the failing resource count for each. ``` ``` Who owns the "Encryption at rest" control, and which automated tests validate it? ``` ## Next steps Full reference for connecting MCP clients to Vanta. Pull test results programmatically. Useful for CI and dashboards. Surface vulnerable assets with approaching SLA deadlines. Get an API token and automate your Vanta account with code. # Vanta SDKs Source: https://developer.vanta.com/docs/sdks Official Vanta SDKs for building against the Vanta API in your language of choice. **SDKs are currently only available for the Auditor API.** The [Manage Vanta API](/reference/manage-vanta/overview) and the [Build Integrations API](/reference/build-integrations/overview) are not yet supported. Vanta publishes official, type-safe SDKs for the [Auditor API](/reference/audits/overview). Each SDK is generated from the same OpenAPI specification, so you get the same coverage and behavior across languages — with idiomatic ergonomics for your stack. Pick the SDK for your language to get started. Click an SDK below to view installation instructions, examples, and the full source on GitHub. Developer-friendly, fully type-safe SDK for Node.js, Deno, Bun, and the browser. ```bash theme={"system"} npm add vanta-auditor-api-sdk ``` [View on GitHub →](https://github.com/VantaInc/vanta-auditor-api-sdk-typescript) Idiomatic Java SDK distributed via Maven Central. Requires JDK 11 or later. ```groovy theme={"system"} implementation 'com.vanta:vanta-auditor-api:0.3.0' ``` [View on GitHub →](https://github.com/VantaInc/vanta-auditor-api-sdk-java) ## What's included Both SDKs are generated from the Vanta Auditor API OpenAPI spec and ship with everything you need to build production integrations: Methods for every Auditor API resource, including audits, evidence, controls, comments, frameworks, tests, and auditors. Built-in support for the `bearerAuth` scheme. Configure once at client initialization and you're ready to call any endpoint. Static types for every request and response model so you catch mistakes at compile time, not in production. Structured error types and configurable retry strategies so your integration stays resilient under real-world conditions. First-class support for paginated endpoints like `audits.list` and `audits.listEvidence`. Override the default server URL per client and enable HTTP debug logging while developing. ## Versioning and support Both SDKs are currently in **beta**. Pin to a specific version so your builds stay reproducible — breaking changes may occur between minor versions until the SDKs reach `1.0.0`. The SDKs are generated programmatically — manual edits to internal files will be overwritten on the next release. To report an issue or request a feature, open an issue or pull request on the relevant GitHub repository. # Vanta MCP server Source: https://developer.vanta.com/docs/vanta-mcp Let AI agents use the Vanta API. Connect Claude Code, Cursor, Perplexity, and other AI tools using the Vanta MCP server. The Vanta MCP server lets AI assistants like Claude, Cursor, and Perplexity call the Vanta API on your behalf. They can securely query controls, remediate failing tests, and act on your compliance data through the [Model Context Protocol](https://modelcontextprotocol.io). This guide explains how to connect Vanta MCP to your AI tool of choice. Vanta's remote MCP server is currently in **beta** and released to all customers. ## Find your MCP URL Vanta hosts a separate MCP server in each region. Find the region for your Vanta instance and use that URL. | Region | MCP URL | | - | - | | United States | `https://mcp.vanta.com/mcp` | | Europe | `https://mcp.eu.vanta.com/mcp` | | Australia | `https://mcp.aus.vanta.com/mcp` | The setup steps below use the **US** URL (`https://mcp.vanta.com/mcp`) as an example. If your instance is in the EU or AUS, substitute the matching URL from the table above. ## Prerequisites Before connecting, confirm the following: * **Vanta role.** You must be a Vanta Admin. The MCP server is not currently accessible to non-Admin users. * **Supported AI tool.** You need access to at least one of: Claude Code, Cursor, Perplexity, Codex, or an AI tool that supports remote MCPs. ## Claude Code You can connect Claude Code to Vanta MCP by adding the server manually or by installing the official Vanta plugin. ### Manual MCP setup Run the following command in your terminal: ```bash theme={"system"} claude mcp add --transport http vanta https://mcp.vanta.com/mcp ``` In Claude Code, run `/mcp` and select **vanta**. A webpage will open in your Vanta app to authorize MCP — click **Allow**. Once authorized, you're ready to start using the Vanta MCP server. Manual setup gives you access to all Vanta MCP tools but does not include the plugin's built-in skills (`/vanta:fix-test`, `/vanta:list-tests`). ### Claude Code plugin The [Vanta plugin](https://github.com/VantaInc/vanta-mcp-plugin) bundles Vanta's MCP server, purpose-built remediation skills, and slash commands into a single easy-to-install package for Claude Code. Use it to discover and prioritize failing tests, generate infrastructure-as-code fixes directly in your repository, and open pull requests without leaving your editor. In the **Claude Code CLI** (not claude.ai in a browser), run the three commands below **in order**. The marketplace must be registered before the plugin can install. ```bash theme={"system"} /plugin marketplace update anthropics/claude-plugins-official /plugin install vanta-mcp-plugin@claude-plugins-official /reload-plugins ``` **Type the commands** rather than pasting them. Claude Code treats a leading `/` in pasted text as a file-path trigger and can open a file picker instead of running the slash command. Run `/mcp`, select **Vanta**, choose your region, and complete the OAuth flow in your browser. You skipped the first command. Run `/plugin marketplace update anthropics/claude-plugins-official` first to register the marketplace, then re-run the install command. Confirm you're running the commands inside the **Claude Code CLI** (the terminal application), not a web chat window. Slash commands like `/plugin` and `/mcp` only work inside Claude Code. If you added the server manually with `claude mcp add`, finish the OAuth step by running `/mcp` and selecting **vanta**. The entry appears there once the client has loaded the configuration. Once connected, you'll have access to: * A **remediation skill** that combines MCP data with your local repo context to generate targeted IaC fixes. * **Slash commands** that streamline common workflows into single actions: * `/vanta:fix-test`: generate code changes to fix a failing compliance test and open a PR. * `/vanta:list-tests`: show prioritized failing tests relevant to your codebase. ### Troubleshooting the plugin install Claude Code installs the plugin entirely through its plugin marketplace. You never need to `git clone` it directly. If `/plugin install vanta-mcp-plugin@claude-plugins-official` fails with `remote: Repository not found` or `fatal: repository ... not found`, check the following in order: * **Update Claude Code.** The plugin marketplace requires a recent version of Claude Code. Upgrade to the latest release and try again. * **Refresh the marketplace first.** Always run `/plugin marketplace update anthropics/claude-plugins-official` before `/plugin install`. Installing without a fresh marketplace listing is the most common cause of "not found" errors. * **Check network access to GitHub.** Claude Code fetches the plugin from `github.com/anthropics/claude-plugins-official` and `github.com/VantaInc/vanta-mcp-plugin`. If you're on a VPN or behind a corporate proxy that blocks GitHub, the install will fail. Confirm you can reach both URLs from the same machine. * **Fall back to manual setup.** If the plugin install continues to fail, use [Manual MCP setup](#manual-mcp-setup) instead. You lose the bundled slash commands but keep access to every Vanta MCP tool. ## Add to Cursor Open **Settings** in Cursor. Select **Tools & MCP → Add custom MCP**. Paste the following configuration: ```json theme={"system"} { "mcpServers": { "vanta": { "url": "https://mcp.vanta.com/mcp" } } } ``` Cursor connects directly to the Vanta MCP server and has access to all Vanta tools. The Claude Code plugin skills (`/vanta:fix-test`, `/vanta:list-tests`) are Claude Code-specific and are not available in Cursor. ## Add to Claude Cowork In Claude Cowork, add the Vanta plugin from the plugin directory. Under **Manage Plugins → Connectors**, install the Vanta MCP server as a custom connector using the URL for your region. Complete the OAuth flow when prompted. Adding custom connectors in Claude Cowork requires the appropriate permission. If you don't have it, ask your Claude Cowork administrator. For the full walkthrough with screenshots, see [Connecting to Vanta MCP — Claude Cowork](https://help.vanta.com/en/articles/14094979-connecting-to-vanta-mcp#h_d3e8ff47d9) in the Vanta Help Center. ## Add to Perplexity In Perplexity, set up a new **remote custom connector**. For the URL, enter `https://mcp.vanta.com/mcp` (or your regional endpoint). For **Authentication**, select **OAuth** and complete the authorization flow. ## Other MCP-compatible clients Vanta MCP is a standard remote MCP server. Any tool that can connect to a remote MCP endpoint with OAuth can connect to Vanta. That includes VS Code (via an MCP-capable extension), Codex, and other emerging MCP clients. The setup steps above (Claude Code, Cursor, Perplexity) are the officially tested paths. Other clients aren't formally validated, but typically work with the same two pieces of configuration: * **Server URL.** Use `https://mcp.vanta.com/mcp` for US tenants, or `https://mcp.eu.vanta.com/mcp` for EU tenants. See [Find your MCP URL](#find-your-mcp-url). * **Authentication.** OAuth. Sign in as a Vanta Admin when the browser flow opens. Consult your client's documentation for where to register a remote MCP server. If your client can't reach the hosted server, you can also run the [open-source `@vantasdk/vanta-mcp-server`](https://github.com/VantaInc/vanta-mcp-server) locally and point your client at the local process instead. ## What your AI agents can do with Vanta MCP Once connected, your AI assistant can: * **Remediate failing tests.** List failing compliance tests, inspect which entities are out of scope, and get the context needed to fix them. * **Manage controls.** Browse controls and their framework mappings, list associated tests, and access linked evidence documents. * **Assess vendor risk.** Review vendors, run security assessments, manage risk attributes, and track compliance documentation. * **Track vulnerabilities.** Surface vulnerable assets and monitor remediation progress. * **Govern policies.** List, download, and upload policy documents across your compliance program. * **Analyze compliance gaps.** Enumerate framework requirements and identify coverage gaps across SOC 2, ISO 27001, and more. ## Resources Official Vanta plugin for Claude Code. Bundles the hosted MCP server with remediation skills and slash commands. Open-source, self-hosted MCP server (`@vantasdk/vanta-mcp-server`) that runs Vanta MCP locally with your own OAuth credentials. Learn more about the open protocol that powers Vanta MCP and other AI tool integrations. # Subscribe to webhook events Source: https://developer.vanta.com/docs/webhooks Receive real-time HTTP notifications when events happen in Vanta — register an endpoint, verify Svix signatures, and handle retries — instead of polling the API. This guide sets up a webhook integration so your server receives real-time `POST` notifications when events happen in Vanta instead of polling the API. You'll register an endpoint, implement a handler that verifies signatures, and confirm an event end to end. ## Before you begin This guide is for developers building a server that receives Vanta webhooks. You'll need: * A publicly accessible **HTTPS** endpoint on your server to receive webhook `POST` requests. * Access to **Settings → Webhooks** in the Vanta dashboard, to register the endpoint and copy its signing secret. * The official [Svix](https://www.svix.com/) library for your language — recommended for signature verification. Webhooks are powered by [Svix](https://www.svix.com/), an enterprise webhook delivery platform, so you get automatic retries, delivery guarantees, and signature verification out of the box. For the full event catalog, payloads, and schemas, see the [Webhook event reference](/reference/webhooks/overview). In the Vanta dashboard, register the URL that will receive events. An endpoint is a URL on your server that receives webhook `POST` requests from Vanta. 1. Navigate to **Settings → Webhooks**. 2. Click **Add Endpoint**. 3. Enter your endpoint URL (must be HTTPS). 4. Browse the available event types and select the ones relevant to your integration — see the [Webhook event reference](/reference/webhooks/overview) for the full catalog of events, payloads, and schemas. Leave the selection blank to receive all events. 5. Click **Create** to register the endpoint. Then open the endpoint and copy its **Signing Secret** (it starts with `whsec_`) from the **Signing Secret** section — you'll use it to verify signatures in the next steps. Implement a server-side handler that can receive the webhook request you just configured. Signature verification requires the **raw request body** as a string, not a parsed object. Make sure your framework preserves the raw body on the webhook route. For example, in Express use `express.raw({ type: 'application/json' })` instead of `express.json()`. Keep the following in mind as you build: Your endpoint must be publicly accessible over HTTPS. Return a `2xx` status code within 15 seconds to acknowledge receipt. If you don't, the delivery is marked as failed and [retried](/reference/webhooks/overview#retry-schedule). Webhook requests won't include CSRF tokens, so CSRF protection must be disabled for the webhook endpoint. Return a `2xx` immediately, then handle the event in a background job or queue. This prevents timeouts on long-running operations. Webhook delivery is "at least once," so your endpoint may receive the same event more than once. Use the `svix-id` header to deduplicate events. Webhook signatures let you confirm that messages are actually sent by Vanta and not a malicious third party. Verification isn't strictly required, but **always verify signatures in production**. Each webhook message includes `svix-id`, `svix-timestamp`, and `svix-signature` headers used for verification — see [Delivery format](/reference/webhooks/overview#delivery-format) in the event reference for what each header contains. The simplest way to verify signatures is to use the official Svix libraries. Install the library for your language and use the `Webhook.verify` method. You can find your endpoint's signing secret in the Vanta webhook dashboard by clicking the endpoint and looking in the **Signing Secret** section. ```javascript Node.js theme={"system"} import { Webhook } from "svix"; const secret = "whsec_..."; // Your signing secret const wh = new Webhook(secret); app.post("/webhook", (req, res) => { try { const payload = wh.verify(req.body, req.headers); // payload is the verified JSON body console.log("Verified webhook:", payload); res.status(200).send("OK"); } catch (err) { console.error("Verification failed:", err.message); res.status(400).send("Invalid signature"); } }); ``` ```python Python theme={"system"} from svix.webhooks import Webhook secret = "whsec_..." # Your signing secret wh = Webhook(secret) def handle_webhook(request): try: payload = wh.verify(request.body, request.headers) # payload is the verified dict print("Verified webhook:", payload) return HttpResponse(status=200) except Exception as e: print("Verification failed:", e) return HttpResponse(status=400) ``` ```go Go theme={"system"} import svix "github.com/svix/svix-webhooks/go" secret := "whsec_..." // Your signing secret wh, _ := svix.NewWebhook(secret) func handleWebhook(w http.ResponseWriter, r *http.Request) { payload, err := io.ReadAll(r.Body) if err != nil { http.Error(w, "Bad request", http.StatusBadRequest) return } err = wh.Verify(payload, r.Header) if err != nil { http.Error(w, "Invalid signature", http.StatusBadRequest) return } // payload is verified w.WriteHeader(http.StatusOK) } ``` ```ruby Ruby theme={"system"} require "svix" secret = "whsec_..." # Your signing secret wh = Svix::Webhook.new(secret) post "/webhook" do begin payload = wh.verify(request.body.read, request.env) # payload is the verified hash puts "Verified webhook: #{payload}" status 200 rescue Svix::WebhookVerificationError => e puts "Verification failed: #{e.message}" status 400 end end ``` If you prefer not to use a library, you can verify signatures manually: 1. Extract the `svix-id`, `svix-timestamp`, and `svix-signature` headers. 2. Concatenate `{svix-id}.{svix-timestamp}.{body}` (the raw request body as a string). 3. Base64-decode the signing secret (remove the `whsec_` prefix first). 4. Compute an HMAC-SHA256 of the signed content using the decoded secret. 5. Base64-encode the result and compare it against the signature(s) in the `svix-signature` header (split by space, each prefixed with `v1,`). Also verify that the `svix-timestamp` is recent (within 5 minutes) to prevent replay attacks. Before going to production, confirm your endpoint can receive and process webhooks correctly. 1. Go to **Settings → Webhooks** in the Vanta dashboard. 2. Select the endpoint you want to test. 3. Navigate to the **Testing** tab. 4. Choose an event type and click **Send Example**. This sends a test message with an example payload to your endpoint, letting you confirm your server verifies and handles it correctly. * Verify that your endpoint URL is correct and publicly accessible over HTTPS. * Ensure that CSRF protection is disabled for the webhook endpoint. * Check that your server is returning a `2xx` status code. * Make sure you are using the **raw request body** (not a parsed JSON object) when verifying the signature. * Confirm that the signing secret matches the one displayed in the webhook dashboard. * Check that you haven't accidentally modified or re-serialized the request body before verification. Your endpoint must respond within 15 seconds. If your processing takes longer, acknowledge the webhook immediately with a `200` response and handle the event asynchronously in a background job or queue. If your endpoint was down for an extended period, recover missed events through the webhook dashboard: 1. Go to **Settings → Webhooks**. 2. Select the affected endpoint. 3. Browse the message history to find failed deliveries. 4. Click **Retry** on individual messages, or use **Bulk Retry** to replay all failed messages within a time range. ## Congratulations You've built a webhook integration. Your endpoint now receives verified, real-time events from Vanta, acknowledges them within the retry window, and processes them idempotently — no polling required. As you add event types to your subscription, consult the [Webhook event reference](/reference/webhooks/overview) for each one's payload and schema. ## Next steps Browse every event type, with payloads, schemas, and examples. Use webhooks alongside the Manage Vanta API to react to events in real time. Become a Vanta partner and push resources into customers' Vanta accounts. # Vanta Developer Hub Source: https://developer.vanta.com/index Build on Vanta — the developer hub for the Manage Vanta, Build Integrations, and Auditor APIs, the Vanta MCP server, SDKs, webhooks, and integration partner program.
# Vanta Developer Hub

How can I help you automate compliance, build integrations, or get work done with AI?

Quickstarts

Start building in minutes

Use cases

See what others build on Vanta

Reference

Explore the Developer Hub

Partners

Reach 16,000+ Vanta customers

List your integration in the Vanta Integration Marketplace
Become an integration partner and list your integration in the Vanta Integration Marketplace to security-conscious teams already automating compliance with Vanta.
Become a partner →
Tools & SDKs

Save time building using these tools

# Auditor API Source: https://developer.vanta.com/reference/audits/overview Auditor API — programmatically conduct audits in Vanta: read audit data, manage information requests, and review evidence. The Auditor API is for **audit firms** conducting audits of their customers' Vanta tenants. Use it to list active audits, pull controls and evidence, manage information requests, and review the resources, personnel, and monitored computers in scope for each engagement. ## Who is this API for? This API is for **registered Vanta Audit Partners** — audit firms running SOC 2, ISO, HIPAA, and other engagements through Vanta. It is not available to Vanta customers automating their own tenant or to ISVs building marketplace integrations. | You are... | Use this API to... | | - | - | | **An audit firm / auditor** with a Vanta Audit Partner registration | List your active audits, pull controls and evidence, create and respond to information requests, and feed audit data into your own audit-management tooling. | Don't see the **Auditor API** option in your Vanta navigation? Your firm needs to be set up as a Vanta Audit Partner first — contact your Vanta representative. ## When to use this API Reach for Auditor endpoints when you want to: * **List and inspect audits** assigned to your firm — pull controls, framework codes, in-scope people, and monitored computers. * **Manage information requests (IRs)** programmatically — create custom IRs, accept or flag evidence, comment on items, and share the IR list with the customer. * **Pull evidence** attached to audits and IRs into your own review workflow or audit-management platform. * **Create custom controls and evidence requests** that supplement Vanta's built-in audit scaffolding. New to the API? Walk through the [Conduct an Audit quickstart](/docs/quickstart/conduct-audit) to register an auditor application, get an access token, and list your first audit. ## Authentication Auditor applications use the **`client_credentials`** OAuth flow. Create an application from the **Auditor API** section of the Vanta app (visible only to registered audit partners), then exchange your `client_id` / `client_secret` at the token endpoint for an access token scoped to your firm's audits. | | | | - | - | | **Endpoint** | `POST /oauth/token` | | **Base URL** | `https://api.vanta.com`  ·  `https://api.vanta-gov.com` | | **Content-Type** | `application/json` | | **Grant type** | `client_credentials` | **Request body** | Field | Type | Required | Description | | - | - | - | - | | `client_id` | string | yes | OAuth client ID from your application on the **Auditor API** page in Vanta. | | `client_secret` | string | yes | OAuth client secret from your application. | | `scope` | string | yes | Space-separated list of [Auditor API scopes](#scopes), e.g. `auditor-api.audit:read`. | | `grant_type` | string | yes | Must be `client_credentials`. | ```bash cURL theme={"system"} curl --request POST 'https://api.vanta.com/oauth/token' \ --header 'Content-Type: application/json' \ --data '{ "client_id": "vci_your_client_id", "client_secret": "vcs_your_client_secret", "scope": "auditor-api.audit:read", "grant_type": "client_credentials" }' ``` ```javascript Node.js theme={"system"} const response = await fetch("https://api.vanta.com/oauth/token", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ client_id: process.env.VANTA_CLIENT_ID, client_secret: process.env.VANTA_CLIENT_SECRET, scope: "auditor-api.audit:read", grant_type: "client_credentials", }), }); const { access_token } = await response.json(); ``` ```python Python theme={"system"} import requests response = requests.post( "https://api.vanta.com/oauth/token", json={ "client_id": client_id, "client_secret": client_secret, "scope": "auditor-api.audit:read", "grant_type": "client_credentials", }, ) access_token = response.json()["access_token"] ``` **Response** ```json theme={"system"} { "access_token": "vat_...", "expires_in": 3600, "token_type": "Bearer" } ``` | Field | Type | Description | | - | - | - | | `access_token` | string | Bearer token. Send as `Authorization: Bearer ` on every API request. | | `expires_in` | integer | Lifetime in seconds. Always `3600` (1 hour). | | `token_type` | string | Always `Bearer`. | No `refresh_token` is issued. When the token expires after one hour, re-exchange your `client_id` / `client_secret` for a fresh one. For the full step-by-step setup, see the [Conduct an Audit quickstart](/docs/quickstart/conduct-audit). **One active token per Application.** Requesting a new token with the same `client_id` / `client_secret` immediately revokes the previous one — any in-flight requests using the old token will fail with `401`. Centralize token issuance and don't run two processes that both mint tokens for the same application. For grant-type tradeoffs, secret rotation, and other foot-guns, see [Authentication concepts](/docs/concepts/authentication). ## Scopes | Scope | Grants | | - | - | | `auditor-api.audit:read` | `GET` access to the [audit endpoints](/api-reference/audits/list-audits). | | `auditor-api.audit:write` | Write access to the audit endpoints (create custom controls, manage IRs, accept evidence, etc.). | | `auditor-api.auditor:read` | `GET` access to the [auditor endpoints](/api-reference/auditors/create-an-auditor). | | `auditor-api.auditor:write` | Write access to the auditor endpoints. | Request only the scopes your tool needs. ## Base URL Use `https://api.vanta.com`, or `https://api.vanta-gov.com` if you're on Vanta Gov. See [Base URLs](/reference/overview#base-urls) for details. ## Pagination List endpoints use cursor-based pagination via the `pageSize` and `pageCursor` query parameters. To page through results: 1. Make the initial request, optionally setting `pageSize` (defaults vary by endpoint). 2. Check `results.pageInfo.hasNextPage` in the response. 3. If `true`, pass `results.pageInfo.endCursor` as the `pageCursor` in your next request. 4. Repeat until `hasNextPage` is `false`. Responses are wrapped as: ```json theme={"system"} { "results": { "data": [ /* ... */ ], "pageInfo": { "endCursor": "...", "hasNextPage": true, "hasPreviousPage": false, "startCursor": "..." } } } ``` ## Rate limits The Auditor API is rate limited per OAuth client (your `client_id`) on a rolling 60-second window. Two limits apply: * A **global cap of 600 requests / minute** across all Auditor API endpoints. * A **per-endpoint limit** — some endpoints are more expensive than others, so they allow fewer requests per minute. Each endpoint's limit is documented on its own reference page. A request is throttled when it exceeds either limit, whichever it reaches first. Exceeding a limit returns `429 Too Many Requests` — back off and retry after a short delay. ## Common workflows Register an auditor application and pull your first audit data. Enumerate the audits assigned to your firm. Create, update, and accept evidence on IRs. Pull evidence attached to controls and IRs. ## OpenAPI specification Generate clients, import into your favorite tool, or browse the schema offline. ## Tools Import the collection to explore endpoints quickly. Official client libraries for the Vanta API. # Build Integrations API Source: https://developer.vanta.com/reference/build-integrations/overview Build Integrations API — push resource data and evidence into Vanta tenants. For partner built integrations and private integrations. The Build Integrations API is for applications that send data **into** Vanta on behalf of a customer. It powers Vanta's marketplace integrations and any private integration you build for your own tenant. Use it to ingest user accounts, devices, vulnerabilities, training records, background checks, and arbitrary custom resources. ## Who is this API for? This API is the **only** Vanta API available to partners and is the right choice for any app that ships data into Vanta. | You are... | Use this API to... | | - | - | | **A partner / ISV** building a marketplace integration | Push your product's data (user accounts, devices, vulnerabilities, etc.) into your customers' Vanta tenants. This is the **only** API partners can use — partners cannot access the Manage Vanta API. | | **A Vanta customer** building a private integration | Connect a homegrown app, on-prem system, or unsupported SaaS tool to your own Vanta tenant. | | **A Vanta customer** syncing data Vanta doesn't natively cover | Define a [custom resource](/docs/concepts/resources#custom-resources) and feed it into Vanta to layer [Custom Tests](https://help.vanta.com/hc/en-us/articles/28012720726036-Creating-Custom-Tests) on top. | Automating workflows inside your **own** Vanta tenant — assigning control owners, querying tests, managing vendors and personnel? Use the [Manage Vanta API](/reference/manage-vanta/overview) instead. (Note: the Manage Vanta API is not available to partners.) ## When to use this API Reach for Build Integrations endpoints when you want to: * **Publish a public integration** to the Vanta marketplace so any Vanta customer can connect your tool. * **Build a private integration** for a homegrown app, on-prem system, or unsupported SaaS tool inside your own tenant. * **Sync resources Vanta doesn't natively support** via [custom resources](/docs/concepts/resources#custom-resources), then layer [Custom Tests](https://help.vanta.com/hc/en-us/articles/28012720726036-Creating-Custom-Tests) on top. Custom resources and Custom Tests are a **private-integration feature**, available to direct Vanta customers building against their own tenant, not to public marketplace integrations. * **Upload file-based evidence** on a customer's behalf to satisfy evidence requests. New here? Walk through the [Build a Private Integration quickstart](/docs/quickstart/build-private-integration) to get OAuth-authorized and push your first resource end to end. ## Authentication All Build Integrations apps authenticate with OAuth 2.0 at the same token endpoint. The grant type depends on how your app is distributed: * **Private integration** — single-tenant, used only inside your own Vanta account. Uses `client_credentials`. Start here if you're building for your own tenant. * **Public integration** — listed in the Vanta marketplace, installable by any customer. Uses `authorization_code` with refresh tokens, one set per customer authorization. | | | | - | - | | **Endpoint** | `POST /oauth/token` | | **Base URL** | `https://api.vanta.com`  ·  `https://api.vanta-gov.com` | | **Content-Type** | `application/json` | ### Private integrations Grant Type: `client_credentials` Your server holds the `client_id` / `client_secret` and exchanges them directly for an `access_token` scoped to your own Vanta tenant. **Request body** | Field | Type | Required | Description | | - | - | - | - | | `client_id` | string | yes | OAuth client ID from your Build Integrations app. | | `client_secret` | string | yes | OAuth client secret from your app. | | `scope` | string | yes | Space-separated list of [Build Integrations scopes](#scopes). | | `grant_type` | string | yes | `client_credentials` | ```bash cURL theme={"system"} curl --request POST 'https://api.vanta.com/oauth/token' \ --header 'Content-Type: application/json' \ --data '{ "client_id": "vci_your_client_id", "client_secret": "vcs_your_client_secret", "scope": "connectors.self:write-resource connectors.self:read-resource", "grant_type": "client_credentials" }' ``` ```javascript Node.js theme={"system"} const response = await fetch("https://api.vanta.com/oauth/token", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ client_id: process.env.VANTA_CLIENT_ID, client_secret: process.env.VANTA_CLIENT_SECRET, scope: "connectors.self:write-resource connectors.self:read-resource", grant_type: "client_credentials", }), }); const { access_token } = await response.json(); ``` ```python Python theme={"system"} import requests response = requests.post( "https://api.vanta.com/oauth/token", json={ "client_id": client_id, "client_secret": client_secret, "scope": "connectors.self:write-resource connectors.self:read-resource", "grant_type": "client_credentials", }, ) access_token = response.json()["access_token"] ``` **Response** ```json theme={"system"} { "access_token": "vat_...", "expires_in": 3600, "token_type": "Bearer" } ``` No `refresh_token` is issued. Requesting a new token with the same `client_id` / `client_secret` immediately revokes the previous one — re-mint just before each sync run. To revoke access, rotate the `client_secret` in the Developer Console (this invalidates active tokens immediately) or delete the application. For the full step-by-step setup, see the [Build a Private Integration quickstart](/docs/quickstart/build-private-integration). ### Public integrations Grant Type: `authorization_code` A customer authorizes your app in the browser at `/oauth/authorize` on **their region's** app host (`app.vanta.com`, `app.eu.vanta.com`, or `app.aus.vanta.com`), and Vanta redirects back to your `redirect_uri` with a short-lived `code` (valid for **30 seconds**). Your server then exchanges the code for a per-customer `access_token` + `refresh_token` pair. The authorize redirect is the only flow that touches the browser-facing app host — and unlike `api.vanta.com`, that host is **regional**: sending an EU or AU customer to `app.vanta.com` instead of their own region's host can fail. All token exchanges and API calls still go to `api.vanta.com` regardless of the customer's region. For Vanta Gov, use `app.vanta-gov.com` and `api.vanta-gov.com`. See [Base URLs and regions](/docs/concepts/authentication#base-urls-and-regions) for the full picture, and the [Build a Public Integration quickstart](/docs/quickstart/build-integration) for the full authorize-redirect flow (including `state` validation and `source_id` semantics). **Request body** | Field | Type | Required | Description | | - | - | - | - | | `client_id` | string | yes | OAuth client ID from your public app. | | `client_secret` | string | yes | OAuth client secret from your application. | | `code` | string | yes | Authorization code from the redirect callback. Expires **30 seconds** after issuance. | | `source_id` | string | yes | Must match the `source_id` you sent on the initial authorize redirect — your internal account identifier for the user. | | `redirect_uri` | string | yes | Must exactly match the `redirect_uri` you sent on the initial authorize redirect, and must be registered in the Developer Console. | | `grant_type` | string | yes | `authorization_code` | ```bash cURL theme={"system"} curl --request POST '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" }' ``` ```javascript Node.js theme={"system"} const response = await fetch("https://api.vanta.com/oauth/token", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ client_id: process.env.VANTA_CLIENT_ID, client_secret: process.env.VANTA_CLIENT_SECRET, code, source_id: accountId, redirect_uri: "https://partner-app.com/oauth/callback", grant_type: "authorization_code", }), }); const tokens = await response.json(); ``` ```python Python theme={"system"} import requests response = requests.post( "https://api.vanta.com/oauth/token", json={ "client_id": client_id, "client_secret": client_secret, "code": code, "source_id": account_id, "redirect_uri": "https://partner-app.com/oauth/callback", "grant_type": "authorization_code", }, ) tokens = response.json() ``` **Response** ```json theme={"system"} { "access_token": "...", "refresh_token": "...", "expires_in": 3600, "token_type": "Bearer" } ``` Store both tokens encrypted at rest, keyed on your internal customer identifier (the same value you used as `source_id`). Each customer authorization is independent — re-running the flow for the same `source_id` revokes that customer's previous tokens, but different customers get separate, isolated token pairs. #### Refreshing the token When the access token expires (1 hour), exchange the `refresh_token` for a new pair. Every refresh rotates the `refresh_token`; the previous one stays valid for **3 hours** to tolerate transient failures — persist the new one immediately. | Field | Type | Required | Description | | - | - | - | - | | `client_id` | string | yes | OAuth client ID. | | `client_secret` | string | yes | OAuth client secret. | | `refresh_token` | string | yes | The current refresh token for this customer. | | `grant_type` | string | yes | `refresh_token` | ```bash cURL theme={"system"} curl --request POST 'https://api.vanta.com/oauth/token' \ --header 'Content-Type: application/json' \ --data '{ "client_id": "vci_your_client_id", "client_secret": "vcs_your_client_secret", "refresh_token": "your_refresh_token", "grant_type": "refresh_token" }' ``` Returns the same `200 OK` response shape as the initial exchange (new `access_token` + new `refresh_token`). Configure automatic retries on `5xx` responses and network errors during refresh. If your refresh handler crashes after issuing the request but before saving the new `refresh_token`, the old one still works for up to 3 hours — but only if you actually retry. #### Revoking access When a customer disconnects your integration on your side, call the Suspend API so Vanta cleans up its side and revokes the tokens. | | | | - | - | | **Endpoint** | `POST /v1/oauth/token/suspend` | | **Base URL** | `https://api.vanta.com`  ·  `https://api.vanta-gov.com` | | **Content-Type** | `application/json` | | Field | Type | Required | Description | | - | - | - | - | | `token` | string | yes | The access or refresh token to revoke. | | `client_id` | string | yes | OAuth client ID. Must match the application that minted the token. | | `client_secret` | string | yes | OAuth client secret. | ```bash cURL theme={"system"} curl --request POST 'https://api.vanta.com/v1/oauth/token/suspend' \ --header 'Content-Type: application/json' \ --data '{ "token": "access_or_refresh_token_to_revoke", "client_id": "vci_your_client_id", "client_secret": "vcs_your_client_secret" }' ``` Returns `200 OK` with an empty body `{}`. Idempotent — calling it on an already-revoked token still returns `200`. Returns `401` if the token doesn't belong to this `client_id`. For grant-type tradeoffs, credential hygiene, and the rest of the foot-guns, see [Authentication concepts](/docs/concepts/authentication). ## Scopes | Scope | Grants | | - | - | | `connectors.self:write-resource` | Push resources into customer Vanta accounts. | | `connectors.self:read-resource` | Read resources you previously pushed (useful for debugging). | | `self:write-document` | Upload file-based evidence on a customer's behalf. | | `self:read-document` | Query evidence requests you previously responded to. | Most integrations request the first two. Add the document scopes only if your integration uploads evidence files. ## Base URL Use `https://api.vanta.com`, or `https://api.vanta-gov.com` if you're on Vanta Gov. See [Base URLs](/reference/overview#base-urls) for details. ## Resource model Build Integrations endpoints follow a `resource_type` pattern: | Method | Endpoint | Use | | - | - | - | | `PUT` | `/v1/resources/` | Idempotent upsert by `uniqueId`. Push the full set of resources you own on a periodic schedule (typically hourly). | | `GET` | `/v1/resources/` | Read back resources you previously pushed. See [Pagination](#pagination) for response shape. | `PUT` is a "state of the world" sync — any resource you previously pushed but omit from a later `PUT` is treated as deleted. There is no separate `DELETE` endpoint. `PUT` is safe to retry on network errors; to sync a large dataset, batch resources into multiple `PUT` calls. See the resource endpoints in the sidebar for the full list of supported types and their schemas. For anything not natively supported, private integrations can use the [custom resource](/docs/concepts/resources#custom-resources) type. Public marketplace integrations are restricted to the built-in resource types listed here. ## Pagination Build Integrations `GET /v1/resources/` endpoints are **not paginated**. Each request returns the full list of resources for the given type in a single `resources` array: ```json theme={"system"} { "resources": [ /* ... */ ] } ``` There are no `pageSize`, `pageCursor`, or `pageInfo` fields. To sync a large dataset, use the corresponding `PUT /v1/resources/` endpoint to push resources to Vanta in batches. ## Payload limits Each `PUT /v1/resources/` request is capped at: | Limit | Value | | - | - | | Maximum resources per `PUT` | 10,000 | | Maximum request body size | 10 MB | Because `PUT` is a "state of the world" sync, every resource you want Vanta to retain for a given `resource_type` must arrive in a **single** request — a follow-up `PUT` to the same type replaces the previous payload rather than appending to it. You can split work *across* resource types (a separate `PUT` per type), but not *within* one. If a payload approaches either cap, scope the sync down to fewer resources to avoid the payload limit. * **Sync only the records you need to act on.** This is most relevant for vulnerability resource types (`PackageVulnerabilityConnectors`, `ApiEndpointVulnerabilityConnectors`, `StaticAnalysisCodeVulnerabilityConnectors`), where scanners often emit thousands of findings spanning Critical, High, Medium, and Low CVEs alongside Known malware and Protestware / potentially unwanted behavior alerts. Customers overwhelmingly take action on Critical and High in Vanta, and those are the severities that drive compliance monitoring. Sending only Critical and High keeps payloads well under the limit and matches what Vanta's own native scanner integrations do. * **Let customers pick severities at install time.** For public integrations, expose a severity selector in your install or settings UI so customers opt into what they want synced. Defaulting to Critical and High covers the common case; customers with specific framework requirements can broaden the set themselves. The same scope-down pattern applies to `Computer` resources when devices carry large installed-application inventories — sync only the security-relevant applications (password managers, antivirus, etc.) rather than the full list. ## Rate limits | Endpoint group | Limit | | - | - | | Build Integrations endpoints | 20 / minute per access token | | OAuth (`/oauth/token`) | 5 / minute | Exceeding a limit returns `429 Too Many Requests`. Back off and retry after a short delay. ## Common workflows Single-tenant integration for your own Vanta account, end to end. Partner flow: register, OAuth, push resources, list in the marketplace. Deep dive on the resource lifecycle, idempotency model, and custom resources. ## OpenAPI specification Generate clients, import into your favorite tool, or browse the schema offline. ## Tools Import the collection to explore endpoints quickly. Add skills that give Cursor, Claude Code, and other AI agents Vanta-specific context. # Manage Vanta API Source: https://developer.vanta.com/reference/manage-vanta/overview Manage Vanta API — automate your Vanta tenant: controls, documents, vendors, personnel, resources, tests, and issues. The Manage Vanta API is the operational surface for **your own Vanta tenant**. Use it to automate the work your team would otherwise click through in the Vanta dashboard — assigning control owners, uploading evidence, syncing personnel, querying test results, and managing vendors. ## Who is this API for? This API is for **Vanta customers** automating their own tenant. It is **not available to partners** building marketplace integrations — partners must use the [Build Integrations API](/reference/build-integrations/overview). | You are... | Use this API to... | | - | - | | **A Vanta customer's security or GRC team** | Automate compliance workflows in your own tenant: assign control owners, surface overdue tasks, manage vendors. | | **A Vanta customer's engineering team** | Pull tests, manage frameworks and automate your compliance program. | Building an integration that syncs data into Vanta from an external tool? Use the [Build Integrations API](/reference/build-integrations/overview) instead. ## When to use this API Reach for Manage Vanta endpoints when you want to: * **Automate compliance workflows** — assign control owners, mark people as not-a-person, surface overdue tasks. * **Report on your security posture** — query controls, tests, vulnerabilities, and resources to feed dashboards or downstream systems. * **Manage your vendor inventory** — create vendors, attach documentation, and apply custom fields. * **Track and triage issues** — list and retrieve issues to sync them into your ticketing system or dashboards. If you're new to the API, start with the [Manage Vanta quickstart](/docs/quickstart/manage-vanta) to authenticate and make your first call. ## Authentication Manage Vanta apps use the **`client_credentials`** OAuth flow. Create a **Manage Vanta** application in the [Developer Console](https://app.vanta.com/settings/developer-console), then exchange your `client_id` / `client_secret` at the token endpoint for an access token scoped to your own Vanta tenant. | | | | - | - | | **Endpoint** | `POST /oauth/token` | | **Base URL** | `https://api.vanta.com`  ·  `https://api.vanta-gov.com` | | **Content-Type** | `application/json` | | **Grant type** | `client_credentials` | **Request body** | Field | Type | Required | Description | | - | - | - | - | | `client_id` | string | yes | OAuth client ID from your Manage Vanta application. | | `client_secret` | string | yes | OAuth client secret from your application. | | `scope` | string | yes | Space-separated list of [Manage Vanta scopes](#scopes), e.g. `vanta-api.all:read`. | | `grant_type` | string | yes | Must be `client_credentials`. | ```bash cURL theme={"system"} curl --request POST 'https://api.vanta.com/oauth/token' \ --header 'Content-Type: application/json' \ --data '{ "client_id": "vci_your_client_id", "client_secret": "vcs_your_client_secret", "scope": "vanta-api.all:read", "grant_type": "client_credentials" }' ``` ```javascript Node.js theme={"system"} const response = await fetch("https://api.vanta.com/oauth/token", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ client_id: process.env.VANTA_CLIENT_ID, client_secret: process.env.VANTA_CLIENT_SECRET, scope: "vanta-api.all:read", grant_type: "client_credentials", }), }); const { access_token } = await response.json(); ``` ```python Python theme={"system"} import requests response = requests.post( "https://api.vanta.com/oauth/token", json={ "client_id": client_id, "client_secret": client_secret, "scope": "vanta-api.all:read", "grant_type": "client_credentials", }, ) access_token = response.json()["access_token"] ``` **Response** ```json theme={"system"} { "access_token": "vat_...", "expires_in": 3600, "token_type": "Bearer" } ``` | Field | Type | Description | | - | - | - | | `access_token` | string | Bearer token. Send as `Authorization: Bearer ` on every API request. | | `expires_in` | integer | Lifetime in seconds. Always `3600` (1 hour). | | `token_type` | string | Always `Bearer`. | No `refresh_token` is issued. When the token expires after one hour, re-exchange your `client_id` / `client_secret` for a fresh one. Most integrations request a new token at the start of each scheduled run. **One active token per Application.** Requesting a new token with the same `client_id` / `client_secret` immediately revokes the previous one — any in-flight requests using the old token will fail with `401`. Centralize token issuance and don't run two processes that both mint tokens for the same application. For grant-type tradeoffs, secret rotation, and other foot-guns, see [Authentication concepts](/docs/concepts/authentication). ## Scopes | Scope | Grants | | - | - | | `vanta-api.all:read` | `GET` access to all Manage Vanta endpoints. | | `vanta-api.all:write` | `PUT`, `PATCH`, `POST`, `DELETE` access to all Manage Vanta endpoints. | | `vanta-api.documents:read` | `GET` access to document endpoints. | | `vanta-api.documents:list` | `GET` access to list documents. | | `vanta-api.documents:write` | Write access to document endpoints. | | `vanta-api.documents:upload` | Upload files via the [document upload endpoint](/api-reference/documents/upload-file-for-document). | | `vanta-api.vendors:read` | `GET` access to vendor endpoints. | | `vanta-api.vendors:write` | Write access to vendor endpoints. | | `vanta-api.issues:read` | `GET` access to issue endpoints. | Request only the scopes your application needs. Requesting a scope that doesn't match your application type returns `invalid_scope`. ## Base URL Use `https://api.vanta.com`, or `https://api.vanta-gov.com` if you're on Vanta Gov. See [Base URLs](/reference/overview#base-urls) for details. ## Pagination List endpoints use cursor-based pagination via the `pageSize` and `pageCursor` query parameters. To page through results: 1. Make the initial request, optionally setting `pageSize` (defaults vary by endpoint). 2. Check `results.pageInfo.hasNextPage` in the response. 3. If `true`, pass `results.pageInfo.endCursor` as the `pageCursor` in your next request. 4. Repeat until `hasNextPage` is `false`. Responses are wrapped as: ```json theme={"system"} { "results": { "data": [ /* ... */ ], "pageInfo": { "endCursor": "...", "hasNextPage": true, "hasPreviousPage": false, "startCursor": "..." } } } ``` Many list endpoints also support filters — see the per-endpoint reference for available options. ## Trust Center Trust Center endpoints (`/trust-centers/{slugId}/...`) require your Trust Center's `slugId` as a path parameter. To find it: 1. In Vanta, navigate to **Trust Center > Overview**. 2. In the top right, copy the unique URL for your Trust Center — it looks like `https://app.vanta.com/your-domain.com/trust/tz7gh0fvb2ymzbl34hca2w`. The `slugId` is the final segment (in this example, `tz7gh0fvb2ymzbl34hca2w`). 3. If you've configured a custom domain, visit your public Trust Center, view source, and look for the `data-slug` attribute on the `` element. Trust Center slugId location ## Rate limits | Endpoint group | Limit | | - | - | | Manage Vanta endpoints | 50 / minute | | OAuth (`/oauth/token`) | 5 / minute | Exceeding a limit returns `429 Too Many Requests`. Back off and retry after a short delay. ## Common workflows Programmatically assign control ownership across your framework. Attach evidence to controls, vendors, or tests. Surface overdue tasks, offboard people, and mark non-personnel. Build dashboards from failing tests and resources. ## OpenAPI specification Generate clients, import into your favorite tool, or browse the schema offline. ## Tools Import the collection to explore endpoints quickly. Connect AI assistants to the Vanta API. Subscribe to events and receive real-time updates. # API Overview Source: https://developer.vanta.com/reference/overview The Vanta API is a RESTful JSON API that lets you automate workflows, integrate external data, and access audit information programmatically. Vanta exposes three APIs, each with its own audience, auth flow, and scopes. Pick the one that matches what you're building — every API-specific detail (scopes, pagination, rate limits, workflows) lives in its overview. Automate your own Vanta tenant — controls, documents, vendors, personnel, tests. Push data into customer Vanta tenants — for marketplace partners and private connectors. For Vanta Audit Partners — pull audit data and manage information requests. New to the API? Start with a [quickstart](/docs/quickstart/manage-vanta) to get authenticated and make your first call. ## Base URLs Use the base URL that matches your **Vanta deployment**, not your region. Standard Vanta tenants — US, EU, and AU alike — all use the same base URL. Only **Vanta Gov** customers use a separate one. | Product | Region | Base URL | | - | - | - | | Vanta | US, EU, AU | `https://api.vanta.com` | | Vanta Gov | US Government Cloud | `https://api.vanta-gov.com` | `api.eu.vanta.com` and `api.aus.vanta.com` exist, but only return an HTTP `308` redirect to `https://api.vanta.com` — they are not usable API endpoints in their own right. Always call `https://api.vanta.com` directly. Many HTTP and OAuth client libraries (including Python's `urllib`) don't automatically replay a `POST` body through a redirect, so calling the regional hostname can turn a working token request into a confusing failure — a `308` with a plain-text body instead of the JSON you're expecting. ## Authentication Every Vanta API request requires an `Authorization: Bearer ` header. All three APIs share a single OAuth 2.0 token endpoint — the grant type, scopes, and request body depend on which API you're calling. | | | | - | - | | **Endpoint** | `POST /oauth/token` | | **Base URL** | `https://api.vanta.com`  ·  `https://api.vanta-gov.com` | | **Content-Type** | `application/json` | | **Token lifetime** | 1 hour | | **Rate limit** | 5 requests / minute, shared across all APIs | See your API's overview for the exact request body, code samples, and response shape: | API | Grant type | Auth section | | - | - | - | | **Manage Vanta** | `client_credentials` | [Authentication](/reference/manage-vanta/overview#authentication) | | **Build Integrations** (Private) | `client_credentials` | [Authentication](/reference/build-integrations/overview#authentication) | | **Build Integrations** (Public) | `authorization_code` | [Authentication](/reference/build-integrations/overview#authentication) | | **Auditor API** | `client_credentials` | [Authentication](/reference/audits/overview#authentication) | **One active token per Application.** Requesting a new token with the same `client_id` / `client_secret` immediately revokes the previous one — any in-flight requests using the old token will fail with `401`. For `authorization_code` apps, this applies *per `source_id`* (per customer authorization), not globally. For the underlying model — grant-type tradeoffs, refresh-token rotation semantics, and the rest of the foot-guns — see [Authentication concepts](/docs/concepts/authentication). ## Scopes Each API exposes its own set of scopes. Requesting a scope that doesn't match your application type returns an `invalid_scope` error. See the scope tables in each API's overview: * [Manage Vanta scopes](/reference/manage-vanta/overview#scopes) * [Build Integrations scopes](/reference/build-integrations/overview#scopes) * [Auditor API scopes](/reference/audits/overview#scopes) ## Versioning The Vanta API does not officially support versioning. All requests target a single, unversioned API surface — `https://api.vanta.com` for standard Vanta tenants, and `https://api.vanta-gov.com` for Vanta Gov tenants. Vanta does not introduce breaking changes to existing endpoints — that includes removing or renaming fields, changing field types, altering the meaning of existing values, or adding new required parameters. All API changes are strictly additive: new endpoints, new optional parameters, and new response fields. Clients should be written to tolerate the addition of new fields. Any deprecations will be announced in advance via the [Changelog](/docs/changelog). ## Error codes The API uses standard HTTP status codes to signal success or failure. Error responses include a JSON body with a `message` field describing the problem. | Code | Meaning | | - | - | | `200` / `201` | Success | | `400` | Bad request — malformed params or wrong types | | `401` | Unauthorized — missing or invalid auth header | | `403` | Forbidden — authenticated but not allowed | | `404` | Not found — resource or endpoint doesn't exist | | `422` | Unprocessable entity — semantically invalid request | | `429` | Too many requests — rate limit exceeded | | `500` | Internal server error | | `503` | Service unavailable | | `504` | Gateway timeout | Per-API rate limits and pagination shapes are documented in each API's overview: * Manage Vanta: [rate limits](/reference/manage-vanta/overview#rate-limits) · [pagination](/reference/manage-vanta/overview#pagination) * Build Integrations: [rate limits](/reference/build-integrations/overview#rate-limits) · [pagination](/reference/build-integrations/overview#pagination) * Auditor API: [rate limits](/reference/audits/overview#rate-limits) · [pagination](/reference/audits/overview#pagination) ## OpenAPI specifications Download the OpenAPI 3.0 spec for each API to generate clients, import into your favorite tool, or browse the schema offline. OpenAPI spec for the Manage Vanta API. OpenAPI spec for the Build Integrations API. OpenAPI spec for the Auditor API. ## Tools and SDKs Import the collection to explore endpoints quickly. Connect AI assistants to the Vanta API via Model Context Protocol. Official client libraries for the Vanta API. Subscribe to events and receive real-time updates. # Webhook events Source: https://developer.vanta.com/reference/webhooks/overview Reference for every webhook event including payloads, schemas, and examples. This reference documents every **event type** Vanta can deliver to a registered webhook endpoint, along with its payload schema and an example body. The payload documented for each event is the event body. New to webhooks? Follow the step-by-step [Subscribe to webhook events](/docs/webhooks) guide to register an endpoint, verify signatures, and handle retries. ## Domains Every event type is a stable identifier in the form `v1...`. Events are grouped into the following domains. Browse each domain in the sidebar to see its individual events, payloads, and schemas. | Domain | What it covers | | - | - | | **Questionnaire** | Questionnaire lifecycle and export events | | **Trust Center** | Trust Center access request events | | **Vendor** | Vendor risk decision events | | **Information Request** | Audit information request (IRL) status, comment, and evidence events | | **Evidence** | Audit evidence lifecycle, status, and comment events | | **Control** | Audit control comment events | The **Information Request**, **Evidence**, and **Control** domains are auditor-specific. These events are only delivered to [Audit Partner](/reference/audits/overview) accounts during an active audit engagement. All other domains are delivered to your own Vanta account. ## Delivery format Vanta sends each event as an HTTP `POST` with the event payload as the JSON body. Every delivery includes the following headers: | Header | Description | | - | - | | `svix-id` | The unique message identifier. Use it to deduplicate events. | | `svix-timestamp` | The timestamp of the message attempt (seconds since epoch). | | `svix-signature` | The Base64-encoded signature(s), space-delimited. Use it to [verify the request](/docs/webhooks#verify-webhook-signatures) originated from Vanta. | Treat IDs in payloads as opaque strings. To fetch the full object referenced by an event, call the corresponding [Manage Vanta API](/reference/manage-vanta/overview) endpoint with the ID from the payload. ## Retry schedule A delivery is considered failed if your endpoint doesn't respond with a `2xx` status code within 15 seconds, including network timeouts. Vanta automatically retries failed deliveries using an exponential backoff schedule: | Attempt | Delay after previous attempt | | - | - | | 1 | Immediately | | 2 | 5 seconds | | 3 | 5 minutes | | 4 | 30 minutes | | 5 | 2 hours | | 6 | 8 hours | | 7 | 1 day | | 8 | 2 days | After all retry attempts are exhausted (approximately 5 days total), the message is marked as failed. You can also manually retry failed messages from the webhook dashboard, or recover missed events as described in the [Webhooks guide](/docs/webhooks#test-your-endpoint). ## Next steps Register an endpoint, verify signatures, and handle retries. Look up the full objects referenced in webhook payloads.