> For the complete documentation index, see [llms.txt](https://docs.nullify.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.nullify.ai/api-reference/api-reference/api-admin/configuration.md).

# Configuration and Policies

These endpoints read and change tenant-wide settings: who security work is routed to, how long findings may stay open (SLAs), the pull request gate, the manager agent's guardrails, CSPM scan cadence and fix-effort weights. A last group stores the calling user's UI preferences and saved views. Authenticate as described in [Authentication](/api-reference/api-reference/authentication.md); people and roles are covered in [Users](/api-reference/api-reference/api-admin/users.md) and teams in [Teams](/api-reference/api-reference/api-admin/teams.md).

Unless a section says otherwise, every call is scoped to a workspace with a provider query parameter such as `githubOwnerId`, `gitlabGroupId`, `azureOrganizationId`, `bitbucketWorkspaceId` or `installationId`, and the call returns 400 when none resolves to a tenant. Read calls need the `ConfigRead` permission and write calls need `ConfigWrite`, except where noted. These settings are replaced or merged as documented per call; none of them starts a scan or job by itself.

## Security owner and routing

The security owner is the person or team lead Nullify falls back to when it needs someone to hand security work to. The routing exclusion list names people Nullify must never pick as a fix-PR reviewer, direct-message recipient or default ticket assignee.

### Get the security owner

Returns the confirmed selection as `teamId` and `userId` (one of them, or both empty when nothing is set), `resolvedUserId` (the active person the selection resolves to today, which follows the team lead when a team is selected) and `suggestions`, contacts Nullify has observed in saved Slack conversations with their `interactionCount`. Suggestions never change the selection. Requires `ConfigRead`.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/admin/config/security-owner" method="get" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-a96d8165240befab9d431c87b16a7387b6914215%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

### Set the security owner

Selects either a team (`teamId`, which follows its current lead) or a person (`userId`). Send both empty to clear the selection. Sending both returns 400, as does an id that is not a team or non-bot person in your tenant, or a selection that resolves to someone on the routing exclusion list. The response is the new state, in the same shape as the read call. Requires `ConfigWrite`.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/admin/config/security-owner" method="put" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-a96d8165240befab9d431c87b16a7387b6914215%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

### Get routing exclusions

Returns the people Nullify must not route to, each expanded to the identities it matches on (`currentLogin`, `userId`, `providerUserId`, `gitUserRefs`, `slackId`, `teamsId`, `linearId`, `jiraId`), plus the security-owner `fallback` that replaces them and whether it is `eligible`. `unresolved` lists the identity kinds that could not be resolved for a person (`account`, `gitAccountId`, `messaging`), each a way the exclusion can be bypassed. `source` is `curated` for entries added through this API; `service_account` entries are computed from a service-account classification, and `nullify_staff` entries are Nullify employees in your GitHub org or with a provider-verified native identity in your tenant, staff identified by their Nullify email in your live Slack or Teams directory, and operator-granted accounts, added only where Nullify has turned staff exclusion on for your tenant; both are read-only. Caller-created accounts and identity mappings do not establish membership. Identity mappings only enrich otherwise eligible Git accounts; messaging-only staff do not expose mapped Git identities. Curated entries retain their saved login and inherit computed identities for the same person. Nullify employees stay visible in your user list so you can review and revoke their access. Unlike most reads, this one requires `ConfigWrite`, so a viewer who holds only `ConfigRead` cannot see who is on the list.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/admin/config/routing-exclusions" method="get" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-a96d8165240befab9d431c87b16a7387b6914215%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

### Set routing exclusions

Replaces the whole list. Each entry needs a `providerId` (a git provider: GitHub, GitLab, Azure DevOps or Bitbucket) and a `login`; send an empty `users` array to clear it. The list holds at most 50 curated people, and duplicates are collapsed. Entries returned by the read call with a computed `source` are dropped rather than saved and do not count toward the limit. The call returns 400 for an invalid entry, for more than 50 people, or when the list would exclude the current security owner. The response is the stored list in the read call's shape. Requires `ConfigWrite`.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/admin/config/routing-exclusions" method="put" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-a96d8165240befab9d431c87b16a7387b6914215%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

## Service level agreements (SLAs)

An SLA sets the maximum days allowed to fix a finding of a given severity or priority, and whether extensions are allowed. Valid severities are `CRITICAL`, `HIGH`, `MEDIUM` and `LOW`; valid priorities are `URGENT`, `IMPORTANT`, `MEDIUM` and `LOW`. Create upper-cases and validates these values, so lowercase is accepted there; the update and bulk-save calls do not validate them, so send the uppercase enumerations. Changes are recorded in the tenant audit log.

### List SLAs

Returns every SLA configured for the tenant in `slas`, or an empty array when none exist. Requires `ConfigRead`.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/admin/sla" method="get" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-a96d8165240befab9d431c87b16a7387b6914215%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

### Create an SLA

Creates one SLA. `maxDaysToFix` must be greater than 0 and at least one of `severity` or `priority` must be set. The schema marks both as required, but either one on its own is accepted. If an SLA already exists for the same severity the call fails and nothing is changed; use the update or bulk-save call to change it. Returns the stored SLA, including its generated `id`. Requires `ConfigWrite`.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/admin/sla" method="post" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-a96d8165240befab9d431c87b16a7387b6914215%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

### Save several SLAs

Upserts a list of SLAs in one call, which is the usual way to set a whole policy. Each entry is matched to an existing SLA by `severity`, so saving a severity that already has an SLA updates it and keeps its original id; an entry with no `id` gets a new one. An empty `slas` list is rejected. Entries are written one by one, so a failure part way can leave earlier entries saved. Returns the ids you submitted (or generated) as `slaIds`; for a severity that already had an SLA these are not necessarily the stored ids, so list the SLAs to read them. Requires `ConfigWrite`.

```bash
curl -s -X PUT \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <TOKEN>" \
  -d '{"slas":[{"severity":"CRITICAL","priority":"URGENT","maxDaysToFix":7,"allowExtensions":false}]}' \
  'https://api.<TENANT>.nullify.ai/admin/sla/bulk?githubOwnerId=1234'
```

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/admin/sla/bulk" method="put" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-a96d8165240befab9d431c87b16a7387b6914215%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

### Update an SLA

Changes one SLA by `slaId`, taken from the list call. Only the fields you send (`severity`, `priority`, `maxDaysToFix`, `allowExtensions`) change; the rest keep their stored values. Returns 404 when the id does not exist in your tenant. Unlike create, this call does not re-validate the values you send. Requires `ConfigWrite`.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/admin/sla/{slaId}" method="patch" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-a96d8165240befab9d431c87b16a7387b6914215%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

## Fix effort

### Get the fix effort mapping

Returns the story-point weights for easy, medium and hard fixes as `fixEffort.easy`, `medium` and `hard`. A tenant that has never saved a mapping gets the defaults 1, 3 and 8 with an empty `id`. Requires `ConfigRead`.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/admin/fix-effort" method="get" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-a96d8165240befab9d431c87b16a7387b6914215%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

### Set the fix effort mapping

Saves the weights. Send the `id` from the read call to replace the stored mapping, or an empty `id` to create it. Replacing sends the whole object, so include all three values. Requires `ConfigWrite`.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/admin/fix-effort" method="put" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-a96d8165240befab9d431c87b16a7387b6914215%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

## Pull request gate

The PR gate decides when the Nullify pull request check fails and whether Nullify reviews pull requests. A tenant that has never configured it gets an information-only check that always passes, with PR reviews on. See [Configuration – Pull Requests](/configuration/configuration-pull-requests.md) for each control.

### Get PR gate settings

Returns the findings controls `findingsPolicy` (`none` or `confirmed`) and `cvssEnforcement`, and the independent scan-failure control `failOnIncompleteCoverage`; `minPriority` (`URGENT` or `IMPORTANT`); `prReviewsEnabled` and the review options `allowApprovingReviews` and `allowRequestChangesReviews` (both off by default, so a clean PR gets no approval and concerns are not merge-blocking); an optional `scaBlockCvssThreshold` that overrides the default 9.0 CVSS cutoff `cvssEnforcement` fails a pull request on without AI confirmation; and the legacy `enabled`, derived from the findings controls. The `scpm` object reports the supply-chain half of the gate; only its `gateEnabled` and `minPriority` are specific to your tenant, the rest is platform-wide. Requires `ConfigRead`.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/admin/pr-gate-settings" method="get" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-a96d8165240befab9d431c87b16a7387b6914215%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

### Set PR gate settings

Replaces the whole setting, so send every field you want kept. `enabled` and `minPriority` are required, `minPriority` must be `URGENT` or `IMPORTANT`, and `scaBlockCvssThreshold` must be between 0 and 10; omitting it resets the cutoff to the default. With `findingsPolicy`, `enabled` must be true exactly when `findingsPolicy` is `confirmed` or `cvssEnforcement` is on, and any other `findingsPolicy` value (including the retired `net_new` and `triaged_confirmed`) is rejected; each is a `400`. `failOnIncompleteCoverage` is independent of the findings controls; omitting it keeps the stored value. Returns the stored values. Requires `ConfigWrite`.

```bash
curl -s -X PUT \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <TOKEN>" \
  -d '{"findingsPolicy":"confirmed","cvssEnforcement":true,"failOnIncompleteCoverage":false,"enabled":true,"minPriority":"IMPORTANT","prReviewsEnabled":true}' \
  'https://api.<TENANT>.nullify.ai/admin/pr-gate-settings?githubOwnerId=1234'
```

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/admin/pr-gate-settings" method="put" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-a96d8165240befab9d431c87b16a7387b6914215%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

## Manager agent

### Get manager settings

Returns the manager agent's stored guardrails in `settings` (`blockedActionTypes`, `groundRules`, `automatedThreatInvestigations`, which defaults to off) and, in `installed`, whether each integration class it needs is connected: `tickets`, `prCreation` and `messaging`. The agent acts on an action only when it is not blocked and its integration is installed, so check both. A tenant with no saved settings returns nothing blocked. Requires `ConfigRead`.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/admin/manager/settings" method="get" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-a96d8165240befab9d431c87b16a7387b6914215%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

### Update manager settings

Updates any of the three fields and leaves omitted ones unchanged. `blockedActionTypes` takes action types or the group aliases `PULL_REQUESTS`, `TICKETS` and `MESSAGING`; an empty array unblocks everything, and an unknown entry returns 400. `groundRules` is free text of at most 10,000 characters that is added to the agent's prompt; an empty string clears it. The save records configuration only and does not start or stop an agent run. Requires `ConfigWrite`.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/admin/manager/settings" method="put" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-a96d8165240befab9d431c87b16a7387b6914215%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

## Cloud posture scan cadence

### Get the CSPM scan cadence

Returns `cspmScanCadence`. An empty string means no cadence is configured, which is scanned daily. A 5xx can be a transient database failure and is worth retrying. Requires `ConfigRead`.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/admin/settings/cspm-scan-cadence" method="get" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-a96d8165240befab9d431c87b16a7387b6914215%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

### Set the CSPM scan cadence

Sets `cspmScanCadence` to one of `daily`, `weekly`, `fortnightly`, `monthly`, `on_change` or `manual`; an empty string clears it back to daily. Any other value returns 400. The daily cloud-posture run skips a tenant already scanned inside its window, so the setting changes when scans happen and does not start one. Requires `ConfigWrite`.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/admin/settings/cspm-scan-cadence" method="put" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-a96d8165240befab9d431c87b16a7387b6914215%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

## UI preferences

UI preferences are a free-form JSON object that the Nullify web app stores per user. They belong to the calling user, keyed on the identity in the token, so these three calls need no permission beyond tenant access. A token that carries no user identity is rejected with 401.

### Get UI preferences

Returns the caller's `preferences` object (empty when nothing is stored) and `updatedAt`.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/admin/ui/preferences" method="get" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-a96d8165240befab9d431c87b16a7387b6914215%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

### Update UI preferences

Merges the supplied `preferences` object into the stored one at the top level: a key you send replaces the stored value for that key, and keys you leave out are kept. The serialized object may be at most 512 KiB. Returns the merged result.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/admin/ui/preferences" method="put" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-a96d8165240befab9d431c87b16a7387b6914215%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

### Delete UI preferences

Wipes the caller's stored preferences. It is idempotent: the response always has `deleted: true`, even when nothing was stored.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/admin/ui/preferences" method="delete" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-a96d8165240befab9d431c87b16a7387b6914215%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

## Saved views

A saved view stores a filter state for a page, as an opaque string in `data`. Views have a `viewPageType` of `OVERVIEW` or `TRIAGE` and a `viewOwnerType` of `ORGANIZATION` (shared across the tenant) or `USER` (private to the creator). These calls require `FindingRead` or `FindingWrite`, and take the tenant from your token, so no provider query parameter is needed. Service-account tokens have no personal identity: they see only organization views, can create only `ORGANIZATION` views (a `USER` view returns 401), and cannot reach any user's private view.

### List saved views

Returns the tenant's organization views plus the caller's own user views in `savedViews`. Requires `FindingRead`.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/admin/ui/savedViews" method="get" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-a96d8165240befab9d431c87b16a7387b6914215%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

### Create a saved view

Creates a view. `viewPageType`, `viewOwnerType`, `name` and `data` must all be non-empty or the call returns 400. The server sets the owner: `ORGANIZATION` views belong to the tenant, anything else is stored as a `USER` view owned by the caller, whatever `viewOwnerId` you send. Returns the stored view. Requires `FindingWrite`.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/admin/ui/savedViews" method="post" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-a96d8165240befab9d431c87b16a7387b6914215%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

### Update a saved view

Rewrites the view named by `savedViewId`, taken from the list call, with the supplied `viewPageType`, `name` and `data`. The owner type and owner cannot be changed. Returns 404 when the id does not exist, or when it is another user's private view. Requires `FindingWrite`.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/admin/ui/savedViews/{savedViewId}" method="patch" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-a96d8165240befab9d431c87b16a7387b6914215%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

### Delete a saved view

Soft-deletes the view named by `savedViewId` and returns its `id`. Returns 404 when the id does not exist or is another user's private view; any caller with `FindingWrite` can delete an organization view. Requires `FindingWrite`.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/admin/ui/savedViews/{savedViewId}" method="delete" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-a96d8165240befab9d431c87b16a7387b6914215%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

## Staff package feeds

These two operations are in the published spec but are not for customer use. `/admin/operator/package-feeds` manages the private package registry connections that Nullify staff attach to a tenant, and it is staff-only. Customer API tokens are rejected: the call needs a verified human Nullify staff identity (service identities are also refused) and an explicit tenant selector, and returns 403 otherwise. You cannot use it to manage your own feeds. It is documented here only so the reference is complete.

### Read staff package feeds

Staff only. Lists the package-registry connections for the tenant named by exactly one provider selector (for example `githubOwnerId`), with credentials redacted. The optional `connectionId` query parameter narrows it to one connection and returns 404 if it is not a package feed of that tenant.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/admin/operator/package-feeds" method="get" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-a96d8165240befab9d431c87b16a7387b6914215%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

### Control a staff package feed

Staff only. Applies one change to a package-feed connection: `operation` is `create`, `rotate`, `probe` or `disconnect`, and `reason` (at most 1,024 characters) is required and recorded with the actor in the audit trail. Changes to an existing connection must send the `expectedRevision` from the read call and fail with a conflict when it is stale. `create` and `rotate` validate the supplied `fields` credentials against the provider before saving, returning 400 if validation fails. The response includes `upstreamRevocationRequired` and, if any exist, `maxOutstandingLeaseExpiry`.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/admin/operator/package-feeds" method="post" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-a96d8165240befab9d431c87b16a7387b6914215%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}
