> ## Documentation Index
> Fetch the complete documentation index at: https://docs.coverbase.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Vendor administration API

> Archive, merge and bulk-edit vendors, manage risk profiles, subprocessors, departments, tags, budgets and discovered vendors.

For AI agents: a documentation index is available at [https://docs.coverbase.com/llms.txt](https://docs.coverbase.com/llms.txt). This page is also available in markdown by appending .md to the URL.

These endpoints manage vendors and services beyond the basic create, read and update calls in the [Vendors API](/api-reference/vendors.md). Each endpoint needs the same permission as the matching screen in the dashboard, and returns the same data the dashboard shows.

All endpoints are scoped to the API key's organization. See [API conventions](/conventions.md) for shared behavior. None of these endpoints honor `Idempotency-Key`.

## Errors

Every error body has this shape:

```json theme={null}
{ "detail": { "code": "vendor_not_found", "message": "No such vendor" } }
```

| Status | Code | Meaning |
| - | - | - |
| `400` | `invalid_request`, `invalid_bulk_action`, `invalid_merge` | The request names something that does not exist or cannot be applied. |
| `403` | `forbidden` | A signed-in user's role does not hold the permission the endpoint needs. |
| `403` | `api_key_not_allowed` | The key's role does not hold the permission the endpoint needs, or the action stays a human decision that a signed-in user must take. |
| `404` | `vendor_not_found`, `service_not_found`, `department_not_found`, `not_enabled`, and others | The record does not exist in your organization, or the feature is not enabled. |
| `409` | `conflict` | The record changed under you, for example a discovery was already reviewed. |
| `422` | `invalid_request`, `score_override_rationale_required` | The body did not validate. A location error also carries `validation`. |

### Actions an API key cannot take

To protect decisions that need a person, an API key gets `403 api_key_not_allowed` on every endpoint that archives, deletes or approves. A signed-in user calling the same endpoint with their own token is allowed. These are:

* `POST /v1/vendors/{vendor_id}/archive`
* `POST /v1/vendors/{vendor_id}/merge` and `POST /v1/vendors/bulk-merge`, because a merge archives the source
* `POST /v1/vendors/bulk-action` with `action: "archive"`
* `DELETE /v1/vendors/{vendor_id}/subprocessors/{subprocessor_id}`
* `POST /v1/vendors/{vendor_id}/subprocessor-proposals/decide`
* `POST /v1/vendor-parent-proposals/decide`
* `POST /v1/services/{service_id}/merge` and `POST /v1/services/{service_id}/promote`, because both archive a service
* `DELETE /v1/departments/{department_id}` and `DELETE /v1/departments/{department_id}/members/{user_id}`
* `POST /v1/vendor-discoveries/approve` and `POST /v1/vendor-discoveries/dismiss`
* `POST /v1/screening-matches/{match_id}/disposition`
* `POST /v1/bills-of-materials/{bom_id}/archive`
* `POST /v1/documents/bulk-action` with `action: "archive"`
* `POST /v1/services/bulk-action` with `action: "archive"`
* `DELETE /v1/vendor-kyc/{kyc_id}`, and `PATCH /v1/vendor-kyc-fields/{field_id}` with `is_archived: true`
* `DELETE /v1/vendor-discovery/aliases/{alias_id}`
* `PATCH /v1/data-classes/{data_class_id}` when it archives or restores a class
* `POST /v1/vendors/{vendor_id}/intelligence/{surface}/revision/{proposal_id}/apply`
* `POST /v1/prequalification-evaluations/{evaluation_id}/override`
* `POST /v1/record-drift/{drift_id}/decide`
* `POST /v1/supplier_reviews/{review_id}/reject` and `POST /v1/legal_entity_assignments/{assignment_id}/reject`
* `DELETE /v1/vendors/{vendor_id}/financial-statements`
* `PUT /v1/vendor-sso/settings`, which needs an organization admin and returns `403 admin_required` to a key

## Endpoints

| Method | Path | Permission |
| - | - | - |
| `POST` | `/v1/vendors/{vendor_id}/archive` | `vendor:archive:org` |
| `POST` | `/v1/vendors/{vendor_id}/merge` | `vendor:update:org`, `vendor:archive:org` |
| `POST` | `/v1/vendors/bulk-merge` | `vendor:update:org`, `vendor:archive:org` |
| `POST` | `/v1/vendors/bulk-action` | Depends on the action |
| `GET` | `/v1/vendor-duplicate-groups` | `vendor:read:org` |
| `GET` | `/v1/vendors/{vendor_id}/nth-parties` | `vendor:read:org` |
| `GET` | `/v1/vendors/{vendor_id}/risk-profile` | `vendor:read:org` |
| `PUT` | `/v1/vendors/{vendor_id}/risk-profile` | `vendor:update:org` |
| `GET` | `/v1/vendors/{vendor_id}/business-unit-dependencies` | `vendor:read:org` |
| `PUT` | `/v1/vendors/{vendor_id}/business-unit-dependencies/{department_id}` | `vendor:update:org` |
| `GET` | `/v1/vendors/{vendor_id}/subprocessors` | `vendor:read:org` |
| `POST` | `/v1/vendors/{vendor_id}/subprocessors` | `vendor:update:org` |
| `PATCH` | `/v1/vendors/{vendor_id}/subprocessors/{subprocessor_id}` | `vendor:update:org` |
| `PATCH` | `/v1/vendors/{vendor_id}/subprocessors/{subprocessor_id}/relationship` | `vendor:update:org` |
| `DELETE` | `/v1/vendors/{vendor_id}/subprocessors/{subprocessor_id}` | `vendor:update:org` |
| `GET` | `/v1/vendors/{vendor_id}/subprocessor-proposals` | `vendor:read:org` |
| `POST` | `/v1/vendors/{vendor_id}/subprocessor-proposals/refresh` | `vendor:update:org` |
| `POST` | `/v1/vendors/{vendor_id}/subprocessor-proposals/decide` | `vendor:update:org` |
| `GET` | `/v1/vendors/{vendor_id}/fourth-party-coverage` | `vendor:read:org` |
| `GET` | `/v1/vendors/{vendor_id}/corporate-family` | `vendor:read:org` |
| `GET` | `/v1/vendor-parent-proposals` | `vendor:read:org` |
| `POST` | `/v1/vendor-parent-proposals/decide` | `vendor:update:org` |
| `GET` | `/v1/vendors/{vendor_id}/financial-stability` | `vendor:read:org` |
| `GET` | `/v1/vendors/{vendor_id}/financial-stability/peers` | `vendor:read:org` |
| `POST` | `/v1/vendors/{vendor_id}/financial-stability/peers/refresh` | `vendor:read:org` |
| `GET` | `/v1/vendors/{vendor_id}/risk-domain-scores` | `vendor:read:org` |
| `GET` | `/v1/vendors/{vendor_id}/risk-domain-scores/{risk_domain_id}` | `vendor:read:org` |
| `POST` | `/v1/vendors/{vendor_id}/risk-domain-scores` | `vendor:update:org` |
| `GET` | `/v1/vendors/{vendor_id}/risk-changes` | `vendor:read:org` |
| `GET` | `/v1/vendors/{vendor_id}/budget` | `contract:read:org` |
| `PUT` | `/v1/vendors/{vendor_id}/budget` | `contract:update:org` |
| `GET` | `/v1/vendors/{vendor_id}/budget-summary` | `contract:read:org` |
| `POST` | `/v1/vendors/{vendor_id}/budget-request` | `contract:update:org` |
| `POST` | `/v1/services/{service_id}/merge` | `service:update:org`, `service:archive:org` |
| `POST` | `/v1/services/{service_id}/relink` | `service:update:org` |
| `POST` | `/v1/services/{service_id}/relink/confirm` | `service:update:org` |
| `POST` | `/v1/services/{service_id}/promote` | `vendor:create:org`, `service:update:org`, `service:archive:org` |
| `GET` | `/v1/services/{service_id}/risk-domain-scores` | `service:read:org` |
| `POST` | `/v1/services/{service_id}/risk-domain-scores` | `service:update:org` |
| `GET` | `/v1/departments` | `user:read:org` |
| `POST` | `/v1/departments` | `user:update:org` |
| `GET` | `/v1/departments/{department_id}` | `user:read:org` |
| `PATCH` | `/v1/departments/{department_id}` | `user:update:org` |
| `DELETE` | `/v1/departments/{department_id}` | `user:update:org` |
| `POST` | `/v1/departments/{department_id}/members` | `user:update:org` |
| `PATCH` | `/v1/departments/{department_id}/members/{user_id}` | `user:update:org` |
| `DELETE` | `/v1/departments/{department_id}/members/{user_id}` | `user:update:org` |
| `GET` | `/v1/tags` | `tag:read:org` |
| `POST` | `/v1/tags` | `tag:create:org` |
| `PATCH` | `/v1/tags/{tag_id}` | `tag:update:org` |
| `GET` | `/v1/tag-group-settings` | `tag:read:org` |
| `PUT` | `/v1/tag-group-settings` | `tag:update:org` |
| `GET` | `/v1/vendor-discoveries` | `vendor:read:org` |
| `POST` | `/v1/vendor-discoveries/approve` | `vendor:create:org` |
| `POST` | `/v1/vendor-discoveries/dismiss` | `vendor:create:org` |
| `GET` | `/v1/vendors/{vendor_id}/discoveries` | `vendor:read:org` |
| `GET` | `/v1/screening/settings` | `integration:read:org` |
| `GET` | `/v1/vendors/{vendor_id}/screening` | `screening_match:read:org` |
| `PATCH` | `/v1/screening-subjects/{subject_id}` | `screening_match:update:org` |
| `GET` | `/v1/screening-runs` | `screening_match:read:org` |
| `POST` | `/v1/screening-matches/query` | `screening_match:read:org` |
| `GET` | `/v1/screening-matches/{match_id}` | `screening_match:read:org` |
| `POST` | `/v1/screening-matches/{match_id}/disposition` | `screening_match:update:org` |
| `GET` | `/v1/vendor-sso/summary` | `vendor:read:org` |
| `GET` | `/v1/vendors/{vendor_id}/sso` | `vendor:read:org` |
| `GET` | `/v1/vendor-sso/applications` | `vendor:read:org` |
| `PUT` | `/v1/vendor-sso/applications/{application_id}/vendor` | `vendor:update:org` |
| `POST` | `/v1/vendor-sso/applications/confirm` | `vendor:update:org` |
| `POST` | `/v1/vendor-sso/applications/{application_id}/vendor/reset` | `vendor:update:org` |
| `GET` | `/v1/vendor-sso/settings` | `vendor:read:org` |
| `POST` | `/v1/vendor-sso/findings/open` | `finding:create:org` |
| `GET` | `/v1/data-quality-rules` | `vendor:read:org` |
| `PUT` | `/v1/data-quality-rules` | `integration:update:org` |
| `GET` | `/v1/vendors/{vendor_id}/data-quality-score` | `vendor:read:org` |
| `POST` | `/v1/vendors/{vendor_id}/company-registration/proposal` | `vendor:update:org` |
| `POST` | `/v1/vendors/{vendor_id}/company-registration/confirm` | `vendor:update:org` |
| `POST` | `/v1/vendors/{vendor_id}/company-registration/undo` | `vendor:update:org` |
| `POST` | `/v1/vendors/{vendor_id}/company-registration/rematch` | `vendor:update:org` |
| `POST` | `/v1/nth-parties/query` | `vendor:read:org` |
| `GET` | `/v1/bills-of-materials/{bom_id}` | `vendor:read:org` |
| `GET` | `/v1/bills-of-materials/{bom_id}/components` | `vendor:read:org` |
| `POST` | `/v1/bills-of-materials/{bom_id}/archive` | `vendor:update:org` |
| `POST` | `/v1/bills-of-materials/{bom_id}/promote` | `vendor:update:org` |
| `POST` | `/v1/vendors/{vendor_id}/documents/query` | `vendor:read:org` |
| `POST` | `/v1/documents/query` | `vendor:read:org` |
| `POST` | `/v1/documents/expirations/query` | `vendor:read:org` |
| `POST` | `/v1/documents/groups` | `vendor:read:org` |
| `GET` | `/v1/document-types` | `vendor:read:org` |
| `POST` | `/v1/documents/{document_id}/mark-subprocessor` | `vendor:update:org` |
| `POST` | `/v1/documents/{document_id}/autofill` | `vendor:update:org` |
| `POST` | `/v1/documents/{document_id}/alerts/{alert_type}/dismiss` | `vendor:update:org` |
| `POST` | `/v1/documents/bulk-action` | `vendor:update:org` |
| `GET` | `/v1/contract-documents/unlinked` | `vendor:read:org` |
| `POST` | `/v1/screening/ad-hoc` | `screening_match:update:org` |
| `POST` | `/v1/vendors/{vendor_id}/screening/rescreen` | `screening_match:update:org` |
| `POST` | `/v1/vendors/{vendor_id}/screening/people` | `screening_match:update:org` |
| `POST` | `/v1/documents/{document_id}/unlock` | `vendor:update:org` |
| `POST` | `/v1/documents/{document_id}/extract-insights` | `vendor:update:org` |
| `POST` | `/v1/documents/bulk-upload` | `vendor:update:org` |
| `POST` | `/v1/documents/infer-type` | `vendor:update:org` |
| `POST` | `/v1/documents/infer-control-set` | `vendor:update:org` |
| `POST` | `/v1/documents/{document_id}/infer` | `vendor:update:org` |
| `POST` | `/v1/documents/{document_id}/recreate-assessment-report` | `vendor:update:org` |
| `GET` | `/v1/supplier_countries` | `supplier_profile:read:org` |
| `GET` | `/v1/supplier_countries/{country_code}` | `supplier_profile:read:org` |
| `GET` | `/v1/supplier_countries/{country_code}/banks` | `supplier_profile:read:org` |
| `POST` | `/v1/supplier_validation/bank_account` | `supplier_profile:read:org` |
| `POST` | `/v1/supplier_validation/tax_id` | `supplier_profile:read:org` |
| `GET` | `/v1/vendors/{vendor_id}/supplier_profile` | `vendor:read:org` |
| `PATCH` | `/v1/vendors/{vendor_id}/supplier_profile` | `vendor:update:org` |
| `POST` | `/v1/vendors/{vendor_id}/diversity_records` | `supplier_profile:update:org` |
| `POST` | `/v1/update_requests/{request_id}/close` | `supplier_profile:update:org` |
| `POST` | `/v1/update_requests/{request_id}/apply_contacts` | `supplier_profile:approve:org` |
| `GET` | `/v1/supplier_settings` | `org_settings:read:org` |
| `PATCH` | `/v1/supplier_settings` | `org_settings:update:org` |
| `POST` | `/v1/legal_entities` | `org_settings:update:org` |
| `PATCH` | `/v1/legal_entities/{legal_entity_id}` | `org_settings:update:org` |
| `POST` | `/v1/legal_entities/{legal_entity_id}/archive` | `org_settings:update:org` |
| `GET` | `/v1/supplier_reviews` | `supplier_banking:approve:org` |
| `POST` | `/v1/supplier_reviews/{review_id}/reject` | `supplier_banking:approve:org` |
| `POST` | `/v1/legal_entity_assignments/{assignment_id}/reject` | `supplier_profile:approve:org` |
| `POST` | `/v1/legal_entities/import` | `org_settings:update:org` |
| `POST` | `/v1/vendor-kyc` | `vendor:update:org` |
| `GET` | `/v1/vendor-kyc/{kyc_id}` | `vendor:read:org` |
| `PATCH` | `/v1/vendor-kyc/{kyc_id}` | `vendor:update:org` |
| `DELETE` | `/v1/vendor-kyc/{kyc_id}` | `vendor:update:org` |
| `GET` | `/v1/vendors/{vendor_id}/kyc` | `vendor:read:org` |
| `POST` | `/v1/vendor-kyc-fields` | `vendor:update:org` |
| `GET` | `/v1/vendor-kyc-fields` | `vendor:read:org` |
| `GET` | `/v1/vendor-kyc-fields/{field_id}` | `vendor:read:org` |
| `PATCH` | `/v1/vendor-kyc-fields/{field_id}` | `vendor:update:org` |
| `GET` | `/v1/vendors/{vendor_id}/kyc-verifications` | `vendor:read:org` |
| `GET` | `/v1/vendors/{vendor_id}/kyc-verifications/history` | `vendor:read:org` |
| `GET` | `/v1/kyc-verifications/{verification_id}` | `vendor:read:org` |
| `POST` | `/v1/vendors/{vendor_id}/kyc/rerun` | `vendor:update:org` |
| `GET` | `/v1/vendors/{vendor_id}/portal-bank-accounts` | `vendor:read:org` |
| `GET` | `/v1/portal-bank-accounts/{bank_account_id}` | `vendor:read:org` |
| `GET` | `/v1/vendor-discovery/aliases` | `vendor:read:org` |
| `POST` | `/v1/vendor-discovery/aliases` | `vendor:create:org` |
| `PATCH` | `/v1/vendor-discovery/aliases/{alias_id}` | `vendor:update:org` |
| `DELETE` | `/v1/vendor-discovery/aliases/{alias_id}` | `vendor:update:org` |
| `GET` | `/v1/vendors/{vendor_id}/intelligence/{surface}/revision` | `vendor:read:org` |
| `POST` | `/v1/vendors/{vendor_id}/intelligence/{surface}/revision/propose` | `vendor:update:org` |
| `POST` | `/v1/vendors/{vendor_id}/intelligence/{surface}/revision/{proposal_id}/preview` | `vendor:read:org` |
| `POST` | `/v1/vendors/{vendor_id}/intelligence/{surface}/revision/{proposal_id}/apply` | `vendor:update:org` |
| `GET` | `/v1/vendors/{vendor_id}/intelligence/{surface}/versions` | `vendor:read:org` |
| `POST` | `/v1/vendors/{vendor_id}/intelligence/{surface}/versions/{version_number}/restore` | `vendor:update:org` |
| `POST` | `/v1/vendors/{vendor_id}/intelligence/review` | `vendor:update:org` |
| `POST` | `/v1/vendors/{vendor_id}/intelligence-feedback` | `vendor:update:org` |
| `GET` | `/v1/vendors/{vendor_id}/intelligence-refresh-status` | `vendor:read:org` |
| `POST` | `/v1/vendors/{vendor_id}/intel-refresh` | `vendor:update:org` |
| `GET` | `/v1/vendors/{vendor_id}/intel-refresh/{request_id}` | `vendor:read:org` |
| `GET` | `/v1/assessments/{assessment_id}/vendor-outreach-request` | `assessment:read:org` |
| `GET` | `/v1/assessments/{assessment_id}/vendor-outreach-handoff` | `assessment:read:org` |
| `POST` | `/v1/assessments/{assessment_id}/vendor-outreach-handoff/send-once` | `portal:update:org`, `portal:create:org` |
| `GET` | `/v1/vendors/{vendor_id}/data-flows` | `vendor:read:org` |
| `GET` | `/v1/data-flow/label-mapping` | `integration:read:org` |
| `PUT` | `/v1/data-flow/label-mapping` | `integration:update:org` |
| `GET` | `/v1/data-flow/unmatched-apps` | `integration:read:org` |
| `PUT` | `/v1/data-flow/app-link` | `integration:update:org` |
| `PUT` | `/v1/engagements/{engagement_id}/data-scope` | `vendor:update:org` |
| `GET` | `/v1/services/{service_id}/risk-profile` | `service:read:org` |
| `PUT` | `/v1/services/{service_id}/risk-profile` | `service:update:org` |
| `GET` | `/v1/vendors/{vendor_id}/service-risk-attributes` | `vendor:read:org` |
| `GET` | `/v1/data-classes` | `service:read:org` |
| `POST` | `/v1/data-classes` | `org_settings:update:org` |
| `PATCH` | `/v1/data-classes/{data_class_id}` | `org_settings:update:org` |
| `POST` | `/v1/service-risk-profiles/tag-mapping/preview` | `org_settings:update:org` |
| `POST` | `/v1/service-risk-profiles/tag-mapping/apply` | `org_settings:update:org` |
| `POST` | `/v1/nth-parties/filter` | `vendor:read:org` |
| `PATCH` | `/v1/nth-parties/{entity_id}` | `vendor:update:org` |
| `GET` | `/v1/bills-of-materials/latest` | `vendor:read:org` |
| `GET` | `/v1/bills-of-materials` | `vendor:read:org` |
| `GET` | `/v1/bills-of-materials/components` | `vendor:read:org` |
| `GET` | `/v1/ai-inventory` | `vendor:read:org` |
| `POST` | `/v1/vendors/query` | `vendor:read:org` |
| `POST` | `/v1/vendors/filter` | `vendor:read:org` |
| `POST` | `/v1/vendors/name-summaries` | `vendor:read:org` |
| `GET` | `/v1/vendor-status-counts` | `vendor:read:org` |
| `GET` | `/v1/subprocessor-proposals` | `vendor:read:org` |
| `GET` | `/v1/services` | `service:read:org` |
| `GET` | `/v1/services/{service_id}` | `service:read:org` |
| `POST` | `/v1/services/query` | `service:read:org` |
| `POST` | `/v1/services/filter` | `service:read:org` |
| `POST` | `/v1/services/bulk-action` | Depends on the action |
| `GET` | `/v1/entities` | `vendor:read:org` |
| `POST` | `/v1/entities/query` | `vendor:read:org` |
| `GET` | `/v1/entities/{entity_id}` | `vendor:read:org` |
| `GET` | `/v1/entities/{entity_id}/product-lines` | `vendor:read:org` |
| `GET` | `/v1/portfolio-risk` | `vendor:read:org` |
| `POST` | `/v1/assessments/{assessment_id}/scores/compute` | `assessment:update:org` |
| `PUT` | `/v1/vendor-sso/settings` | `vendor:update:org`, organization admin |
| `POST` | `/v1/vendors/{vendor_id}/exports/pdf` | `vendor:export:org` |
| `POST` | `/v1/vendors/{vendor_id}/exports/xlsx` | `vendor:export:org` |
| `POST` | `/v1/services/{service_id}/exports/pdf` | `service:export:org` |
| `POST` | `/v1/services/{service_id}/exports/xlsx` | `service:export:org` |
| `POST` | `/v1/vendors/exports` | `vendor:export:org` |
| `POST` | `/v1/services/exports` | `service:export:org` |
| `POST` | `/v1/vendors/portfolio-exports` | `vendor:export:org` |
| `POST` | `/v1/services/portfolio-exports` | `service:export:org` |
| `GET` | `/v1/vendor-exports/{export_id}` | `vendor:export:org` or `service:export:org` |
| `POST` | `/v1/vendors/imports` | `vendor:create:org` |
| `GET` | `/v1/vendor-info-web-search` | `vendor:create:org` |
| `GET` | `/v1/vendor-certificate-summary` | `vendor:read:org` |
| `POST` | `/v1/prequalification-evaluations/{evaluation_id}/override` | `vendor:update:org` |
| `GET` | `/v1/vendors/{vendor_id}/risk-ratings` | `vendor:read:org` |
| `GET` | `/v1/vendors/{vendor_id}/company-registration` | `vendor:read:org` |
| `GET` | `/v1/dnb-integration/entitlements` | `integration:run:org` |
| `GET` | `/v1/vendors/{vendor_id}/financial-health` | `vendor:read:org` |
| `GET` | `/v1/vendors/{vendor_id}/do-not-use` | `vendor:read:org` |
| `PUT` | `/v1/vendors/{vendor_id}/do-not-use` | `vendor:update:org` |
| `GET` | `/v1/document-type-groups` | `org_settings:read:org` |
| `POST` | `/v1/document-type-groups/enable` | `org_settings:update:org` |
| `GET` | `/v1/passive-assessment-configs` | `vendor:read:org` |
| `GET` | `/v1/passive-assessment-configs/{config_id}` | `vendor:read:org` |
| `POST` | `/v1/passive-assessment-configs` | `org_settings:update:org` |
| `PATCH` | `/v1/passive-assessment-configs/{config_id}` | `org_settings:update:org` |
| `GET` | `/v1/passive-assessment-groups` | `vendor:read:org` |
| `POST` | `/v1/passive-assessment-groups` | `org_settings:update:org` |
| `PATCH` | `/v1/passive-assessment-groups/{group_id}` | `org_settings:update:org` |
| `GET` | `/v1/vendors/{vendor_id}/passive-assessment` | `vendor:read:org` |
| `POST` | `/v1/passive-assessment-data` | `vendor:update:org` |
| `GET` | `/v1/record-drift` | `vendor:read:org` |
| `POST` | `/v1/record-drift/{drift_id}/decide` | `vendor:update:org` |
| `PUT` | `/v1/screening/settings` | `integration:update:org` |
| `GET` | `/v1/screening-profile-groups` | `integration:update:org` |
| `GET` | `/v1/screening/evidence-export` | `screening_match:export:org` |
| `GET` | `/v1/vendors/{vendor_id}/status-page-components` | `vendor:read:org` |
| `GET` | `/v1/vendors/{vendor_id}/financial-statements` | `vendor:read:org` |
| `POST` | `/v1/vendors/{vendor_id}/financial-statements` | `vendor:update:org` |
| `POST` | `/v1/vendors/{vendor_id}/financial-statements/analyze` | `vendor:update:org` |
| `DELETE` | `/v1/vendors/{vendor_id}/financial-statements/documents/{document_id}` | `vendor:update:org` |
| `DELETE` | `/v1/vendors/{vendor_id}/financial-statements` | `vendor:update:org` |
| `GET` | `/v1/vendors/{vendor_id}/financial-statements/export` | `vendor:read:org` |

List endpoints that take `limit` and `offset` return `items`, `total`, `limit` and `offset`. `limit` defaults to `50` and accepts `1` to `200`.

## Archive, merge and bulk-edit vendors

### Archive a vendor

**method** `POST`

`POST /v1/vendors/{vendor_id}/archive`

Archives the vendor together with its assessments, documents and obligations. The vendor then leaves every list. Returns `vendor_id`, `name` and `is_archived: true`.

### Merge two vendors

**method** `POST`

`POST /v1/vendors/{vendor_id}/merge`

Merges another vendor into the path vendor. Every record on the source moves to the path vendor, an empty field takes the source's value, and the source is archived.

**source\_vendor\_id** `string` *required*

The vendor to merge in and archive (`cbvndr_...`).

Returns `vendor_id`, `name` and `source_vendor_id`. Returns `400 invalid_merge` when the two vendors cannot be merged, for example when they are the same vendor.

### Run several merges

**method** `POST`

`POST /v1/vendors/bulk-merge`

Runs up to 100 merges in order. Each pair is its own transaction, so a failed pair is reported and does not undo the pairs before it. Running the same request again is safe: a pair that already merged the same way reports success.

**merges** `object[]` *required*

Each item has `target_vendor_id`, `source_vendor_id` and an optional `strategy`. Use `merge_equal` (the default) to merge and archive the source, `make_service` to turn the source into a service under the target, or `delete_source` to archive the source without moving anything. `make_service` also needs `service:create:org`.

Returns `results` (one per pair, with `success` and `error`), `success_count` and `failure_count`.

To find candidate pairs, call `GET /v1/vendor-duplicate-groups`. It returns groups of live vendors that share a domain, a brand or a similar name, with each vendor's `assessment_count`.

### Change many vendors at once

**method** `POST`

`POST /v1/vendors/bulk-action`

Applies one change to up to 100 vendors. Nothing is written when any vendor, tag, user or status in the request does not exist (`400 invalid_bulk_action`).

**vendor\_ids** `string[]` *required*

Between 1 and 100 vendor IDs.

**action** `string` *required*

One of `tag`, `assign-relationship-owner`, `assign-risk-analyst`, `update-status`, `archive`, `set-next-assessment-date`.

**tag\_ids** `string[]`

For `tag`: up to 15 tags. Required for that action.

**operation** `string` (default: add)

For `tag`: `add` or `remove`.

**user\_id** `string`

For the two assign actions: the user to add. Required for those actions.

**status\_id** `string`

For `update-status`: a vendor status ID. Required for that action.

**next\_assessment\_date** `integer | null`

For `set-next-assessment-date`: unix seconds, or `null` to clear.

The `tag`, `update-status` and `set-next-assessment-date` actions need `vendor:update:org`. The assign actions need `vendor:assign:org`. `archive` needs `vendor:archive:org` and a signed-in user. Returns `action` and `vendor_count`.

```bash cURL theme={null}
curl -X POST "https://api.coverbase.app/v1/vendors/bulk-action" \
  -H "Authorization: Bearer ak_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "vendor_ids": ["cbvndr_e448ba62882143f3ba0c140bb2e30162"],
    "action": "tag",
    "tag_ids": ["cbtag_5f1c0a3e9b2d4c7a8e6f1a2b3c4d5e6f"]
  }'
```

## Risk profile and business units

`GET /v1/vendors/{vendor_id}/risk-profile` returns the vendor's portfolio risk profile: `bcp_documented`, `bcp_last_tested_at`, `rto_hours`, `rpo_hours`, `meets_rto_rpo`, `dr_plan_documented`, `pen_test_last_at`, `ir_plan_documented`, `subprocessor_list_current`, `ai_usage_disclosed`, `ai_data_types`, `data_processing_regions`, `data_types_processed`, `integration_depth` (`deep`, `moderate` or `shallow`), `viable_alternatives_count`, `substitutability_score` and `is_user_edited`. Fields read as their defaults until the profile is saved or extracted from a completed assessment.

`PUT /v1/vendors/{vendor_id}/risk-profile` replaces the editable fields with the body you send. It is a full replace, so an omitted field resets to its default. To change one field, read the profile, change the field and send the whole profile back. A save sets `is_user_edited`, and the automatic extraction never overwrites a user-edited profile.

`GET /v1/vendors/{vendor_id}/business-unit-dependencies` lists the departments that depend on the vendor, each with `criticality` and `usage_description`. Dependencies are derived nightly from the vendor's services.

`PUT /v1/vendors/{vendor_id}/business-unit-dependencies/{department_id}` sets one dependency.

**criticality** `string` *required*

`critical`, `high`, `elevated` or `acceptable`.

**usage\_description** `string`

What the business unit uses the vendor for.

Returns `404` when the department is not a live department of your organization.

## Subprocessors

`GET /v1/vendors/{vendor_id}/subprocessors` returns `subprocessors`, the fourth parties the vendor depends on. `is_user_edited` separates links a person manages from links the subprocessor-list crawl found.

`POST /v1/vendors/{vendor_id}/subprocessors` links a subprocessor. Send either `subprocessor_id` (an existing catalog entry) or `name` (an unknown name creates the entry). Optional fields are `category`, `hq_location`, `inherent_risk_level_id`, `tag_ids`, and `entity_id` or `entity_website` to resolve the company. Send `entity_id` or `entity_website`, not both.

`PATCH /v1/vendors/{vendor_id}/subprocessors/{subprocessor_id}` edits the catalog entry, which every vendor in your organization that links it shares. Send `inherent_risk_level_id: null` to clear the level and `tag_ids: []` to clear the tags.

`PATCH /v1/vendors/{vendor_id}/subprocessors/{subprocessor_id}/relationship` edits your organization's record of the dependency: `is_active`, `dependency_type`, `dependency_detail`, `mode`, `data_scopes`, `description`, `data_class_ids`, `service_ids` and `transfer_regions`. Only the fields you send change. After you edit, the nightly inheritance stops proposing changes to the link.

`DELETE /v1/vendors/{vendor_id}/subprocessors/{subprocessor_id}` unlinks the subprocessor. The link is archived, so the crawl cannot add it back.

Each of these write endpoints returns the vendor's full subprocessor list.

### Subprocessor proposals

`GET /v1/vendors/{vendor_id}/subprocessor-proposals` lists the subprocessors the shared data suggests for the vendor. An organization that inherits automatically has an empty list. `POST .../subprocessor-proposals/refresh` re-scans the vendor now instead of overnight.

`POST /v1/vendors/{vendor_id}/subprocessor-proposals/decide` accepts or rejects proposals.

**accept** `boolean` *required*

`true` links each subprocessor, `false` records a durable rejection.

**proposal\_ids** `string[]`

The proposals to decide. Omit to decide every pending proposal on the vendor.

**rejection\_reason** `string`

Why, when rejecting.

Returns `decided_count`, `accepted_count`, `rejected_count` and `remaining_count`.

`GET /v1/vendors/{vendor_id}/fourth-party-coverage` says how complete and how fresh the vendor's fourth-party list is, per source.

## Corporate family and financial stability

`GET /v1/vendors/{vendor_id}/corporate-family` returns the vendor's ultimate parent and every vendor under it, with the family's engagements, highest residual risk and contract value. It needs the engagement record feature, or it returns `404 not_enabled`.

`GET /v1/vendor-parent-proposals?status=pending` lists parent links the company registers suggest. `status` is `pending` (the default), `accepted` or `rejected`. `POST /v1/vendor-parent-proposals/decide` takes `ids` and a `decision` of `accepted` or `rejected`. An accepted link that would loop the family refuses the whole batch with `422`.

`GET /v1/vendors/{vendor_id}/financial-stability` rates the vendor under your organization's financial stability methodology and returns the filed ratios behind the rating. `GET .../financial-stability/peers` rates the vendor's security peers the same way, and `needs_refresh` says a refresh would read newer SEC figures. `POST .../financial-stability/peers/refresh` returns `202` with `queued`, the number of peers whose figures were queued for reading. These three need Zero Touch Assessments, or they return `404`.

## Risk domain scores and risk changes

`GET /v1/vendors/{vendor_id}/risk-domain-scores` returns `data`, one entry per risk domain with the inherent and residual score and level and the `score_source`. `GET .../risk-domain-scores/{risk_domain_id}` returns one domain.

`POST /v1/vendors/{vendor_id}/risk-domain-scores` creates or updates one domain's score and recomputes the vendor's tier.

**risk\_domain\_id** `string` *required*

The risk domain.

**score\_source** `string` *required*

Where the score comes from, for example `manual` for a score you set by hand or `assessment`.

**inherent\_risk\_score** `number | null`

Send `null` to clear. The same applies to `inherent_risk_level_id`, `residual_risk_score` and `residual_risk_level_id`.

**note** `string`

Required when a `manual` score changes a value. Without it the request returns `422 score_override_rationale_required`.

`GET /v1/services/{service_id}/risk-domain-scores` and `POST /v1/services/{service_id}/risk-domain-scores` do the same for a service, and the write recomputes the vendor rollup.

`GET /v1/vendors/{vendor_id}/risk-changes` returns the vendor's risk-change history, newest first, as `data` and `total_count`. Filter with `risk_type` (`inherent_risk` or `residual_risk`) and pass `include_dismissed=true` to include dismissed changes.

## Budgets

`GET /v1/vendors/{vendor_id}/budget?year=2026` returns the vendor's budget for the year, or `null`.

`PUT /v1/vendors/{vendor_id}/budget?year=2026` sets the budget, replacing the one there.

**amount** `string | null` *required*

The amount, with up to two decimals. `null` clears the budget and the response is `null`.

**currency** `string`

ISO currency code. Without it, the existing budget's currency or your organization's base currency applies.

**note** `string`

A note, up to 2000 characters.

**cpi\_pct** `string`

The CPI rate used to price next year's request.

`GET /v1/vendors/{vendor_id}/budget-summary?year=2026` reads the budget against the contracts that count towards it: `committed_amount`, `remaining_amount`, `percent_used`, `is_over_budget`, the counted `contracts`, and `next_year_request`. Pass `cpi_pct` to price the request at another rate.

`POST /v1/vendors/{vendor_id}/budget-request` saves next year's budget as this year's committed spend raised by CPI. Send `year` and `cpi_pct`. It returns `422` when no CPI rate is available.

## Services

`POST /v1/services/{service_id}/merge` merges `source_service_id` into the path service and archives the source.

`POST /v1/services/{service_id}/relink` moves the service to `target_vendor_id`. A service with no records of its own moves at once and the response is the moved service. Otherwise nothing moves and the response carries `record_counts`. To move the service with the records exclusive to it, send the same body to `POST /v1/services/{service_id}/relink/confirm`.

`POST /v1/services/{service_id}/promote` turns the service into a standalone vendor and archives the service. Send the new vendor's fields under `vendor` (at least `name`). Most records stay with the original vendor, and `moved_record_counts` and `retained_record_counts` say what moved.

## Departments

Departments are business units and user groups. `GET /v1/departments` lists them (pass `include_archived=true` for archived ones) and `GET /v1/departments/{department_id}` returns one with its lead and members.

`POST /v1/departments` returns `201` and takes `name`, `description`, `assignment_strategy` and `lead_user_id`. `PATCH /v1/departments/{department_id}` changes the fields you send; send `description: null` or `lead_user_id: null` to clear one.

`POST /v1/departments/{department_id}/members` adds `user_id` with an optional `rotation_order`, and returns `400` when the user already belongs. `PATCH .../members/{user_id}` changes `member_status`, `inactive_from`, `inactive_to` or `rotation_order`; send `null` for an `inactive_` field to clear the out-of-office window. Every write is recorded on the department's activity feed.

## Tags and tag groups

`GET /v1/tags` lists live tags. `POST /v1/tags` returns `201` and takes `key` (the group), `value` and an optional `color`. It returns `400` when the tag already exists. `PATCH /v1/tags/{tag_id}` changes `key`, `value` or `color`. To archive a tag, use the dashboard.

`GET /v1/tag-group-settings` lists every tag group with a setting: `key`, `rollup_mode`, `ranked_tag_ids` (riskiest first) and `category`.

`PUT /v1/tag-group-settings` sets one group.

**key** `string` *required*

The tag group. A blank key returns `400`.

**rollup\_mode** `string`

How service tags reach the vendor. `union` leaves vendor tags to whoever writes them. `highest_rank` keeps only the riskiest tag across the vendor's active services.

**ranked\_tag\_ids** `string[]`

The group's tags, riskiest first. Tags you leave out become unranked.

**category** `string | null`

The heading the group is filed under. `null` or blank clears it.

Omitted fields keep their values. Changing `rollup_mode` or `ranked_tag_ids` recomputes vendor tags.

## Discovered vendors

These endpoints need the vendor discovery integration, or they return `404`.

`GET /v1/vendor-discoveries` lists vendors your integrations discovered, one row per vendor across sources. Filter with `review_status` (`pending` by default, `approved` or `dismissed`) and `search`.

`POST /v1/vendor-discoveries/approve` takes `discovery_ids` and an optional `target_vendor_id`. Each discovery links to a matching vendor, merges onto `target_vendor_id`, or creates a vendor. The response lists `approved_discovery_ids`, `created_vendor_ids` and `linked_vendor_ids`.

`POST /v1/vendor-discoveries/dismiss` takes `discovery_ids` and an optional `reason`.

Both are all or nothing and return `409` when a discovery was already reviewed. `GET /v1/vendors/{vendor_id}/discoveries` lists every integration that discovered the vendor, with its records.

## Screening

These endpoints need sanctions screening, or they return `404 not_found`. They also need `screening_match` permissions, which API keys do not hold, so call them with a signed-in user's token.

`GET /v1/screening/settings` returns your screening configuration. `GET /v1/vendors/{vendor_id}/screening` returns the vendor's screening subjects (the company and the people you enrolled), their latest runs and their open matches. `GET /v1/screening-runs` lists runs, newest first, and takes `vendor_id`, `subject_id`, `limit` and `offset`.

`POST /v1/screening-matches/query` filters matches, and `GET /v1/screening-matches/{match_id}` returns one match with its evidence and history. To record a decision on a match, a signed-in user sends `POST /v1/screening-matches/{match_id}/disposition`. API keys get `403 api_key_not_allowed`.

`PATCH /v1/screening-subjects/{subject_id}` edits a subject, for example whether it is monitored.

To screen one name once, send `POST /v1/screening/ad-hoc` with `name` and `kind` (`entity` or `person`), and optionally `vendor_id`, `country` and `feeds`. Feeds your organization switched off are refused with `400`. To screen every live subject of a vendor now, send `POST /v1/vendors/{vendor_id}/screening/rescreen`; the response lists `dispatched_subject_ids`. To enroll a person you know belongs to the vendor, send `POST /v1/vendors/{vendor_id}/screening/people` with `name`, and optionally `country`, `role` and `screen_now`. It returns `201` with the new subject.

## Vendor SSO

`GET /v1/vendor-sso/summary` counts the vendors your identity provider shows in use and how many enforce SSO. `GET /v1/vendors/{vendor_id}/sso` lists the applications linked to one vendor. `GET /v1/vendor-sso/applications` lists applications; pass `unlinked=true` or `suggested=true` to narrow it.

To link an application to a vendor, send `PUT /v1/vendor-sso/applications/{application_id}/vendor`. To accept several suggested matches at once, send `POST /v1/vendor-sso/applications/confirm`. To clear a link so matching runs again, send `POST /v1/vendor-sso/applications/{application_id}/vendor/reset`. `GET /v1/vendor-sso/settings` reads the settings. `PUT /v1/vendor-sso/settings` replaces them, and only an organization admin can call it, so an API key gets `403 admin_required`. A change to matching or findings checks every vendor again.

To open an unassigned finding for each approved vendor without SSO that has none yet, send `POST /v1/vendor-sso/findings/open`. Pass `vendor_ids` to limit it and `due_days` to set the due date. The response says how many were `opened`.

## Data quality

These endpoints need the engagement record feature, or they return `404 not_enabled`.

`GET /v1/data-quality-rules` returns the per-tier rules: which fields count, how old a value may be, and the score threshold. `PUT /v1/data-quality-rules` replaces them, and saving any rule turns the daily check on. It returns `422` for an unknown field or a tier listed twice.

`GET /v1/vendors/{vendor_id}/data-quality-score` returns the vendor's latest score and the reasons behind it, or `null` before the daily check has scored it.

## Company registration

`POST /v1/vendors/{vendor_id}/company-registration/proposal` searches the company registers for the vendor's legal entity and returns candidates. Nothing is saved. `POST .../company-registration/confirm` saves one candidate as the vendor's registered company. `POST .../company-registration/undo` reverts the last confirmation, and `POST .../company-registration/rematch` runs the match again. The last three return the saved registration profile.

## Nth parties and bills of materials

`POST /v1/nth-parties/query` filters, sorts and pages the companies your vendors depend on, with the same unified filter body the dashboard uses (`filter`, `sort`, `search`, `limit`, `offset`).

`GET /v1/bills-of-materials/{bom_id}` returns one software or AI bill of materials, and `GET .../components` pages its components with `search` and `component_type`. `POST .../promote` makes it the current bill for its vendor or service. `POST .../archive` archives it and refuses API keys.

## Vendor documents

These endpoints extend the [Documents API](/api-reference/documents.md).

`POST /v1/vendors/{vendor_id}/documents/query` filters, sorts and pages one vendor's documents with the unified filter body (`filter`, `sort`, `search`, `limit`, `offset`, and an optional `group`). `POST /v1/documents/query` does the same across every vendor. `POST /v1/documents/groups` returns document counts by type or status.

`POST /v1/documents/expirations/query` lists every expiry and renewal date across your documents, soonest first, with one row per date. Filter with `search`, `anchor_keys`, `document_type_slugs`, `anchor_date_start` and `anchor_date_end`.

`GET /v1/document-types` lists the document types you can assign, including your custom types. `GET /v1/contract-documents/unlinked` lists contract documents not yet linked to a contract record.

To record a company named in a document as one of the vendor's subprocessors, send `POST /v1/documents/{document_id}/mark-subprocessor` with `company_name`. This also clears the document's company-name mismatch alerts. `POST /v1/documents/{document_id}/autofill` writes the vendor custom fields the document's extracted details fill, and returns `400` when there are none. `POST /v1/documents/{document_id}/alerts/{alert_type}/dismiss` archives the document's active alerts of one type.

`POST /v1/documents/bulk-action` takes `action: "archive"` with `ids`, `action: "update_services"` with `ids` and `service_ids`, or `action: "update_services_granular"` with `items` of `id` and `service_ids`. It returns `updated_count`. Archiving refuses API keys.

To open a password-protected document, send `POST /v1/documents/{document_id}/unlock` with `password`. The unlock runs in the background and the request returns `202`; a document that is not locked returns `400`.

To extract document insights, send `POST /v1/documents/{document_id}/extract-insights`, optionally with `insight_config_ids`. It returns `202` with the queued `insight_extraction` state. Poll `GET /v1/documents/{document_id}` until the state is no longer `running`. A request while an extraction is already running returns `409` with `insight_extraction_running`.

To classify a file before you upload it, send `POST /v1/documents/infer-type` with `filename` and `text_content`, and optionally `allowed_document_slugs` to narrow the answer. `POST /v1/documents/infer-control-set` takes the same body and returns the questionnaire `control_set_id` the file answers, or `null` when none matches.

To rerun inference of one field on a processed document, send `POST /v1/documents/{document_id}/infer` with `field` and optionally `reanalyze: true` to read the content again. It returns the document, and `400` while the document is still processing.

`POST /v1/documents/{document_id}/recreate-assessment-report` rebuilds a Word assessment report document from its template with the placeholder values you send in `vendor_data`, `services_data`, `assessment_data`, `reviews_data`, `agent_data` and `intelligence_data`. It replaces the stored file and returns the document.

To add many documents at once, upload a ZIP with one folder per vendor and send its `org_document_id` to `POST /v1/documents/bulk-upload`. Each folder name must match exactly one vendor and the ZIP may hold no loose files. The response says whether validation passed and lists the matched vendors or the errors; on success the documents are added in the background.

## Know Your Supplier

These endpoints need Know Your Supplier turned on for your organization; otherwise they return `404 not_enabled`. Bank account numbers are always masked here.

`GET /v1/supplier_countries` lists the countries whose bank and tax details can be validated. `GET /v1/supplier_countries/{country_code}` returns that country's bank, tax ID and address rules with your overrides applied, and `GET /v1/supplier_countries/{country_code}/banks` lists its known banks, which is empty for most countries. A country without rules returns `404 country_not_configured`.

To check details before saving them, send `POST /v1/supplier_validation/bank_account` with `bank_country`, `currency` and `values`, or `POST /v1/supplier_validation/tax_id` with `country_code`, `tax_id_type` and `value`. Both return `200` with per-field results, even when the details fail.

`GET /v1/vendors/{vendor_id}/supplier_profile` returns the vendor's bank accounts, sites, tax registrations, diversity records, legal entity assignments and pending bank changes in one response. `PATCH` the same path with `legal_name_local` to set the vendor's legal name in its local script; an empty value clears it.

To record a diversity classification or certification, send `POST /v1/vendors/{vendor_id}/diversity_records` with `category` and its details. A record that fails validation returns `422` with per-field results.

`POST /v1/update_requests/{request_id}/close` withdraws an open update request or marks a returned one reviewed, and returns `409 update_request_closed` when it is already closed. `POST /v1/update_requests/{request_id}/apply_contacts` writes the contact changes the supplier proposed onto the vendor; API keys are refused, so a signed-in user applies them.

`GET /v1/supplier_settings` returns your Know Your Supplier settings. `PATCH /v1/supplier_settings` replaces them with the whole object you send. API keys are refused on the `PATCH`, because these settings decide whether a bank change waits for a person's review.

To add a legal entity that suppliers can be assigned to, send `POST /v1/legal_entities` with `name` and `entity_code`; a code already in use returns `409 duplicate_entity_code`. `PATCH /v1/legal_entities/{legal_entity_id}` changes its name, code, country, description or `active` flag. `POST /v1/legal_entities/{legal_entity_id}/archive` archives it and keeps the assignments suppliers already hold; API keys are refused.

`GET /v1/supplier_reviews` lists the bank changes waiting for a reviewer, optionally for one `vendor_id` or with `include_decided=true`. A signed-in user rejects one with `POST /v1/supplier_reviews/{review_id}/reject` and a `reason`; API keys are refused. Approving a change, and revealing a full account number, happen only in the dashboard, because an approval redirects payments. `POST /v1/legal_entity_assignments/{assignment_id}/reject` rejects a requested legal entity assignment, and API keys are refused there too.

To import legal entities, send a CSV as multipart `file` to `POST /v1/legal_entities/import`. It needs `name` and `entity_code` columns and may carry `country_code` and `description`. Rows upsert on `entity_code`. `dry_run` defaults to `true` and reports `created`, `updated`, `skipped` and per-row `rows` without writing; send `dry_run=false` to write. A file with a missing column or a CSV that does not parse writes nothing and comes back in `schema_errors`. This needs `org_settings:update:org`, which API keys do not hold, so use a key created by a person whose role holds it.

## Know your customer (KYC)

A vendor's KYC record points at three field values: its TIN, business name and business address. Every response masks a TIN to its last four characters, including inside a verification's `input_data`.

`GET /v1/vendors/{vendor_id}/kyc` returns the record, or `404 kyc_record_not_found`. `GET`, `PATCH` and `DELETE /v1/vendor-kyc/{kyc_id}` read, repoint and delete it, and `POST /v1/vendor-kyc` creates one from existing field ids. A vendor has one record; a second returns `400`. Deleting refuses API keys.

`POST /v1/vendor-kyc-fields` records a value, and `GET /v1/vendor-kyc-fields` lists them with `vendor_id`, `field_name` and `is_archived`. `PATCH /v1/vendor-kyc-fields/{field_id}` changes one; archiving refuses API keys.

`GET /v1/vendors/{vendor_id}/kyc-verifications` lists the TIN, OFAC, PEP, watchlist and bank account checks. Add `/history?verification_type=tin` for every run of one type. `GET /v1/kyc-verifications/{verification_id}` returns one.

To rerun the checks from the current values, send `POST /v1/vendors/{vendor_id}/kyc/rerun`. It returns `202`, or `400 kyc_incomplete` without a TIN and business name. The TIN is never stored with the queued run, so if the run does not start, send the request again.

## Portal bank accounts

`GET /v1/vendors/{vendor_id}/portal-bank-accounts` lists the bank accounts a vendor submitted through a portal, and `GET /v1/portal-bank-accounts/{bank_account_id}` returns one. You get metadata only: the account name, payment method, currencies and each detail's type and label with its last four characters. A full account number, routing number, IBAN or Plaid token is never returned.

## Discovery aliases

An alias tells vendor discovery which domain and products a discovered vendor name means. `GET /v1/vendor-discovery/aliases` lists your overrides. `POST` adds one with `source`, `vendor_entity`, `domain` and `product_patterns`, and returns `409 alias_exists` for a duplicate. `PATCH /v1/vendor-discovery/aliases/{alias_id}` changes one, and an explicit `null` clears its domain. `DELETE` removes it and refuses API keys.

## Vendor intelligence revisions, feedback and refresh

`{surface}` is `security` or `financial`. `GET .../intelligence/{surface}/revision` returns your organization's current reading with revised and stored scores. To revise it from text, send `POST .../revision/propose` with `text`. That writes a proposal only. `POST .../revision/{proposal_id}/preview` with `accepted_change_ids` returns the scores the chosen changes would give. `POST .../revision/{proposal_id}/apply` accepts them as a new version and refuses API keys. `GET .../versions` lists versions, and `POST .../versions/{version_number}/restore` makes an earlier one current. `POST /v1/vendors/{vendor_id}/intelligence/review` queues the automated check against the vendor's own site.

To tell Coverbase a tab describes the wrong company or facts, send `POST /v1/vendors/{vendor_id}/intelligence-feedback` with `surface` and `note`, and optionally `website` or `legal_name`. A corrected website or legal name rebuilds every surface. The note is stored on the shared company record.

`POST /v1/vendors/{vendor_id}/intel-refresh` with `surfaces` rebuilds them, skipping any built in the last six hours. Poll `GET /v1/vendors/{vendor_id}/intel-refresh/{request_id}` or `GET /v1/vendors/{vendor_id}/intelligence-refresh-status`.

## Vendor outreach

`GET /v1/assessments/{assessment_id}/vendor-outreach-request` returns the outreach request waiting on an assessment. `GET .../vendor-outreach-handoff` says why a collection was handed to a person because outreach is off. `POST .../vendor-outreach-handoff/send-once` prepares the ask once without turning outreach on. Sending it contacts the vendor, and that stays a person's decision through `POST /v1/vendor-outreach-requests/{request_id}/decision`.

## Data flows

These endpoints need data flow monitoring, or they return `404`. `GET /v1/vendors/{vendor_id}/data-flows` returns 90 days of the vendor's daily flows, the data its engagement declares, and open data-flow findings. `GET` and `PUT /v1/data-flow/label-mapping` read and replace the label-to-data-class mapping. `PUT /v1/engagements/{engagement_id}/data-scope` declares the data classes an engagement may send. `GET /v1/data-flow/unmatched-apps` lists apps no vendor claims, and `PUT /v1/data-flow/app-link` ties one to a vendor. Every change checks the flows again.

## Service risk profiles and data classes

These endpoints need the engagement record feature, or they return `404 not_enabled`. `GET` and `PUT /v1/services/{service_id}/risk-profile` read and set a service's data classes, access level, criticality, regulatory scopes and AI flag. `GET /v1/vendors/{vendor_id}/service-risk-attributes` combines them across a vendor's services. `GET /v1/data-classes` lists your data classes, `POST` adds or renames them by code, and `PATCH /v1/data-classes/{data_class_id}` changes one. `POST /v1/service-risk-profiles/tag-mapping/preview` shows what mapping tags to attributes would change, and `.../apply` backfills it. The data class writes and tag mapping need `org_settings:update:org`, which API keys do not hold, so use a key created by a person whose role holds it.

## More vendor and service reads

`POST /v1/nth-parties/filter` filters nth parties by name or dependent vendor, and `PATCH /v1/nth-parties/{entity_id}` replaces an nth party's tags. `GET /v1/bills-of-materials/latest` and `GET /v1/bills-of-materials` take exactly one of `vendor_id` and `service_id`. `GET /v1/bills-of-materials/components?vendor_id=` searches components across a vendor's bills. `GET /v1/ai-inventory` groups every AI model, provider or dataset on your applied AI bills by `group_by`.

`POST /v1/vendors/query` and `POST /v1/services/query` take the unified filter body. `POST /v1/vendors/filter` and `POST /v1/services/filter` take the structured filters. `GET /v1/vendor-status-counts` counts live vendors by status, `POST /v1/vendors/name-summaries` names vendors by id, and `GET /v1/subprocessor-proposals` pages pending proposals across vendors. `GET /v1/services` lists services, and `GET /v1/services/{service_id}` returns one.

`GET /v1/entities` searches the company directory, `POST /v1/entities/query` takes long id lists in the body, `GET /v1/entities/{entity_id}` returns a company, and `.../product-lines` lists its product lines.

`GET /v1/portfolio-risk` returns risk over time across the portfolio, one series per vendor whose risk changed, filtered by `vendor_id`, `tag_id`, `risk_type`, `source`, `since` and `until`. `POST /v1/assessments/{assessment_id}/scores/compute` recomputes an assessment's scores.

`GET /v1/vendor-certificate-summary`, `GET /v1/vendors/{vendor_id}/risk-ratings`, `GET /v1/vendors/{vendor_id}/company-registration`, `GET /v1/vendors/{vendor_id}/financial-health` and `GET /v1/vendors/{vendor_id}/status-page-components` return what the vendor page shows. `GET /v1/dnb-integration/entitlements` lists your Dun & Bradstreet entitlements.

## Change many services at once

`POST /v1/services/bulk-action` applies one change to up to 100 `service_ids`. `action` is `tag` (up to 15 `tag_ids`, `operation` `add` or `remove`), `assign-relationship-owner` or `assign-watcher` (`user_id`), `update-status` (`status_id`), `set-next-assessment-date` (`next_assessment_date`) or `archive`. Nothing is written when a service, user, status or tag does not exist; that returns `400 invalid_bulk_action`. Every action needs `service:update:org`. Assigning an owner also needs `service:assign:org`, and archiving needs `service:archive:org` and refuses API keys.

## Exports and imports

Exports run in the background. `POST /v1/vendors/{vendor_id}/exports/pdf` and `/exports/xlsx`, and the same under `/v1/services/{service_id}`, return an `odoc_id`. `POST /v1/vendors/exports?file_name=` starts the workbook of every vendor, optionally narrowed by a filter body, and `POST /v1/services/exports` does the same for services. `POST /v1/vendors/portfolio-exports` and `/v1/services/portfolio-exports` start the portfolio PDF. Poll `GET /v1/vendor-exports/{export_id}`. Once `status` is `complete`, it carries a presigned `download_url` valid for `expires_in` seconds, and it is sent with `Cache-Control: no-store`.

To import vendors, services and locations, send the dashboard's vendor workbook as multipart `file` with `timezone` to `POST /v1/vendors/imports`. `dry_run` defaults to `true`. Poll `GET /v1/spreadsheet-import-jobs/{job_id}` for the result.

`GET /v1/vendor-info-web-search?vendor_name=` researches a company on the web before you add it.

## Do Not Use, record drift and settings

`GET` and `PUT /v1/vendors/{vendor_id}/do-not-use` read and set whether a vendor is on the Do Not Use list. A change needs a `reason`. `GET /v1/record-drift` lists vendors whose outside records changed, and `POST /v1/record-drift/{drift_id}/decide` accepts, updates or dismisses each change. Deciding refuses API keys. `POST /v1/prequalification-evaluations/{evaluation_id}/override` overrides a failed prequalification with a `rationale` and refuses API keys.

`GET /v1/document-type-groups` lists document type groups, and `POST /v1/document-type-groups/enable` turns optional ones on. The passive assessment routes read and edit the fields Coverbase fills in from public sources: `/v1/passive-assessment-configs`, `/v1/passive-assessment-groups`, `GET /v1/vendors/{vendor_id}/passive-assessment` and `POST /v1/passive-assessment-data`. The settings writes need `org_settings:update:org`, which API keys do not hold.

`PUT /v1/screening/settings` changes the screening policy, `GET /v1/screening-profile-groups` lists the provider's profile groups, and `GET /v1/screening/evidence-export` returns a CSV of every screened vendor's first and last screen.

## Submitted financial statements

`GET /v1/vendors/{vendor_id}/financial-statements` returns the documents the vendor's financial analysis reads and the analysis, or `null`. `POST` the same path with up to five `document_ids` sets them and analyzes them unless `analyze` is `false`. `POST .../analyze` runs it again. `DELETE .../documents/{document_id}` stops reading one document. `DELETE .../financial-statements` withdraws the submission and refuses API keys. `GET .../export` returns the analysis workbook with `Cache-Control: no-store`, or `404` before an analysis exists.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.