PUT/api/resource-server/apis/{api_server_id}/scopesAuthenticated

Sync a resource server's API scopes

Brings the API scopes the auth server holds for an API server in line with the list its resource server declares in code, in one transaction: scopes the list adds are created (with no created_by), and a listed scope whose description differs, or whose allow_dynamic_clients differs when the entry gives it, is updated. Nothing is ever deleted: deleting a scope drops users' consents and the per-app allowances set for it, so the scopes the list leaves out come back as not_in_manifest for a person to delete in the console. Per-app scope allowances and the API server's own dynamic-client policy are not touched. With dry_run=true the same diff is computed and nothing is written, so CI can fail on drift. Any invalid entry refuses the whole list (400), and a list that would take the API server over 100 scopes is refused with 409. Manifest files can name the JSON Schema served at /json-schema/api-server-scopes.json in their $schema for editor auto-complete and checks. Resource servers built on @schemavaults/auth-server-sdk call this with syncApiServerScopes() (@schemavaults/auth-server-sdk/api-scopes) or auth-server-sdk sync-scopes --manifest <path>; run it once per environment's auth server, before deploying code that requires a new scope.

operationId put_api_resource_server_apis_api_server_id_scopesResource servers

Authentication & permissionsAuthenticated

Any authenticated user

Accepted credentials
Who may call
Any authenticated user
Notes
The assertion's iss / sub must equal the api_server_id path parameter, so a resource server can only define its own API scopes. Every assertion is accepted once.

Path parameters

NameTypeDescription
api_server_id*string

API server id; must equal the assertion's issuer

Query parameters

NameTypeDescription
dry_run"true" | "false"

true reports what the sync would do without writing anything

Request body

Required

application/json
SyncApiServerScopesRequestA scope manifest: every scope the API server defines (at most 100, no value repeated). scope: a single RFC 6749 scope-token (printable ASCII without spaces, " or \, at most 128 characters) that is not an OpenID Connect scope name. description: 1 to 256 characters, shown to users. allow_dynamic_clients: whether dynamically registered clients may be granted the scope; omit it to keep the current value (new scopes default to true). $schema is ignored, so a manifest file validated against /json-schema/api-server-scopes.json is sent as it is. Unknown keys are rejected.
PropertyTypeDescription
$schemastring

URL of this JSON Schema, for editor auto-complete and checks. Ignored by the auth server.

scopes*object[]

Every scope the API server defines (at most 100, each value listed once). Missing scopes are created and changed ones updated; scopes the auth server knows but the list leaves out are reported and never deleted.

maxItems: 100

scope*string

The OAuth 2.0 scope value: one RFC 6749 scope-token (printable ASCII without spaces, '"' or '\'), at most 128 characters, and never an OpenID Connect scope name. It cannot be renamed once defined.

minLength: 1maxLength: 128pattern: ^[\x21\x23-\x5B\x5D-\x7E]+$

description*string

What the scope allows, shown to users on the consent screen (1 to 256 characters after trimming). A changed description updates the scope on the next sync.

minLength: 1maxLength: 256

allow_dynamic_clientsboolean

Whether dynamically registered clients may be granted this scope. Omit it to keep the current value; a new scope defaults to true.

JSONExample
"scopes"
"scope""notes:read"
"description""Read your notes."
"scope""notes:write"
"description""Create, edit and delete your notes."
"allow_dynamic_clients"true

Responses

application/json
SyncApiServerScopesResponseWhat the sync did (or, for a dry run, would do): created and updated scopes (previous holds the earlier values of the fields that changed), the values of the listed scopes that were unchanged, and the scopes the API server defines that the list leaves out (not_in_manifest), which are kept.
PropertyTypeDescription
success*true
data*object
api_server_id*string

minLength: 2maxLength: 64pattern: ^[a-z0-9_-]*$

dry_run*boolean
created*object[]
scope*string

minLength: 1maxLength: 128pattern: ^[\x21\x23-\x5B\x5D-\x7E]+$

description*string

maxLength: 256

allow_dynamic_clients*boolean
updated*object[]
scope*string

minLength: 1maxLength: 128pattern: ^[\x21\x23-\x5B\x5D-\x7E]+$

description*string

maxLength: 256

allow_dynamic_clients*boolean
previous*object
descriptionstring

maxLength: 256

allow_dynamic_clientsboolean
unchanged*string[]
not_in_manifest*object[]
scope*string

minLength: 1maxLength: 128pattern: ^[\x21\x23-\x5B\x5D-\x7E]+$

description*string

maxLength: 256

JSONExample
"success"true
"data"
"api_server_id""string"
"dry_run"true
"created"
"updated"
"unchanged"
"string"
"not_in_manifest"

Example request

bashcurl
curl -X PUT 'https://auth.schemavaults.com/api/resource-server/apis/<api_server_id>/scopes' \
  -H 'Authorization: Bearer <access_token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "scopes": [
    {
      "scope": "notes:read",
      "description": "Read your notes."
    },
    {
      "scope": "notes:write",
      "description": "Create, edit and delete your notes.",
      "allow_dynamic_clients": true
    }
  ]
}'