Docker AI Governance API
HTTP API reference for managing Docker AI Governance policies and rules programmatically.
HTTP+JSON API for managing Docker governance policies and rules.
Resource model. An organization owns one or more policies. Each policy
contains a list of rules grouped into a single domain: either network or
filesystem. A policy's domain is derived from its rule actions; mixing
domains within a single policy is not permitted.
Lifecycle. Create a policy with CreatePolicy, then add rules with CreateRule. Rules can be updated in place with UpdateRule or removed with DeleteRule. Deleting all rules does not delete the policy itself.
Rule evaluation. All rules in a policy are tested against every request.
deny always wins: if any rule matches with decision: deny, the request
is denied regardless of any allow rules.
Enforcement. Organization policies take precedence over local sandbox policies and cannot be overridden by individual users.
Propagation. Policy changes take up to five minutes to reach developer machines after being written.
See https://pagesrvs-backend.pages.dev/docs.docker.com/ai/sandboxes/governance/ for product documentation.
Authentication
bearerAuth
type: http
scheme: bearer
bearer format: JWTShort-lived JWT obtained by exchanging Docker Hub credentials at
POST https://hub.docker.com/v2/auth/token. Pass the JWT in the
Authorization: Bearer <token> header. Tokens expire after a short
period; request a fresh one when you receive a 401.
The password field of the token request accepts any of the following
credential types:
| Type | Format | Notes |
|---|---|---|
| Password | Plain text | Your Docker Hub account password. |
| Personal Access Token (PAT) | dckr_pat_* | Recommended over passwords. Create one under Account Settings → Security. |
| Organization Access Token (OAT) | dckr_oat_* | Scoped to an organization. Create one under Organization Settings → Access Tokens. |
PAT and OAT strings can't be used directly as a bearer token. They must be exchanged at the token endpoint first.
See Docker Hub authentication for full details.
Policies
Policy lifecycle management
/orgs/{org_name}/governance/policiesParameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
org_name | path | string | yes | Docker Hub organization name. |
Responses
▸ 200 Object wrapping an array of policy summaries under `data`. Rule sets are not included; use GetPolicy to fetch a full policy.
{
"data": [
{
"created_at": "2026-04-22T00:00:00Z",
"id": "pol_06evsmp24r1pg71cm8500546pkbn",
"name": "Security Research — hardened",
"org": "my-org",
"scope": {
"teams": [
"d290f1ee-6c54-4b01-90e6-d701748f0851"
]
},
"type": "allowlist_v0",
"updated_at": "2026-04-22T00:00:00Z"
}
]
}▸ 401 Missing or invalid credentials
Schema: Error
{
"error": {
"code": "unauthenticated",
"message": "unauthenticated"
}
}▸ 403 Caller lacks the required permission for this org, or the org is not entitled to use governance.
Schema: Error
{
"error": {
"code": "permission_denied",
"message": "permission denied"
}
}▸ 404 Not found
Schema: Error
{
"error": {
"code": "not_found",
"message": "policy not found"
}
}▸ 500 Internal server error
Schema: Error
{
"error": {
"code": "internal",
"message": "internal error"
}
}/orgs/{org_name}/governance/policiesParameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
org_name | path | string | yes | Docker Hub organization name. |
Request body
Policy name and optional scope.
Content type:
application/json
Schema: CreatePolicyRequest
{
"name": "Security Research — hardened",
"scope": {
"teams": [
"d290f1ee-6c54-4b01-90e6-d701748f0851"
]
}
}Responses
▸ 201 Policy created. Returns the new policy without its rule set.
Schema: Policy
{
"created_at": "2026-04-22T00:00:00Z",
"id": "pol_06evsmp24r1pg71cm8500546pkbn",
"name": "Security Research — hardened",
"org": "my-org",
"scope": {
"teams": [
"d290f1ee-6c54-4b01-90e6-d701748f0851"
]
},
"updated_at": "2026-04-22T00:00:00Z"
}▸ 400 Bad request
Schema: Error
{
"error": {
"code": "invalid_argument",
"message": "name is required"
}
}▸ 401 Missing or invalid credentials
Schema: Error
{
"error": {
"code": "unauthenticated",
"message": "unauthenticated"
}
}▸ 403 Caller lacks the required permission for this org, or the org is not entitled to use governance.
Schema: Error
{
"error": {
"code": "permission_denied",
"message": "permission denied"
}
}▸ 404 Not found
Schema: Error
{
"error": {
"code": "not_found",
"message": "policy not found"
}
}▸ 409 Conflict
Schema: Error
{
"error": {
"code": "conflict",
"message": "policy name already in use"
}
}▸ 500 Internal server error
Schema: Error
{
"error": {
"code": "internal",
"message": "internal error"
}
}/orgs/{org_name}/governance/policies/{policy_id}allowlist_v0 rule set.Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
org_name | path | string | yes | Docker Hub organization name. |
policy_id | path | string | yes | Unique policy identifier. |
Responses
▸ 200 Full policy including its `allowlist_v0` rule set.
Schema: Policy
{
"allowlist_v0": {
"domain": "network",
"rules": [
{
"actions": [
"connect:tcp",
"connect:udp"
],
"decision": "allow",
"id": "rule_06evsm9qjm1pdsk0a8nkfaxy7jna",
"name": "allow research mirrors",
"resources": [
"research.mitre.org",
"cve.mitre.org"
]
}
]
},
"created_at": "2026-04-22T00:00:00Z",
"id": "pol_06evsmp24r1pg71cm8500546pkbn",
"name": "Security Research — hardened",
"org": "my-org",
"scope": {
"teams": [
"d290f1ee-6c54-4b01-90e6-d701748f0851"
]
},
"updated_at": "2026-04-22T00:00:00Z"
}▸ 401 Missing or invalid credentials
Schema: Error
{
"error": {
"code": "unauthenticated",
"message": "unauthenticated"
}
}▸ 403 Caller lacks the required permission for this org, or the org is not entitled to use governance.
Schema: Error
{
"error": {
"code": "permission_denied",
"message": "permission denied"
}
}▸ 404 Not found
Schema: Error
{
"error": {
"code": "not_found",
"message": "policy not found"
}
}▸ 500 Internal server error
Schema: Error
{
"error": {
"code": "internal",
"message": "internal error"
}
}/orgs/{org_name}/governance/policies/{policy_id}Partially updates a policy's metadata. Only fields present in the
request body are updated; absent fields are left unchanged. The scope
object is patched per sub-field: sending teams replaces that list,
while an omitted sub-field is left untouched and an empty list clears
it (org-wide).
The rule set is not modified here — use the rule endpoints for that. At least one field must be present. Returns the policy in both its old and new states. Changes may take up to five minutes to reach developer machines.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
org_name | path | string | yes | Docker Hub organization name. |
policy_id | path | string | yes | Unique policy identifier. |
Request body
Fields to update. Absent fields are left unchanged.
Content type:
application/json
Schema: UpdatePolicyRequest
{
"name": "Security Research"
}{
"scope": {
"teams": [
"d290f1ee-6c54-4b01-90e6-d701748f0851"
]
}
}Responses
▸ 200 Policy updated, returns old and new states.
Schema: UpdatePolicyResponse
{
"new": {
"allowlist_v0": {
"domain": "network",
"rules": [
{
"actions": [
"connect:tcp",
"connect:udp"
],
"decision": "allow",
"id": "rule_06evsm9qjm1pdsk0a8nkfaxy7jna",
"name": "allow research mirrors",
"resources": [
"research.mitre.org",
"cve.mitre.org"
]
}
]
},
"created_at": "2026-04-22T00:00:00Z",
"id": "pol_06evsmp24r1pg71cm8500546pkbn",
"name": "Security Research",
"org": "my-org",
"scope": {
"teams": [
"d290f1ee-6c54-4b01-90e6-d701748f0851"
]
},
"updated_at": "2026-04-22T10:00:00Z"
},
"old": {
"allowlist_v0": {
"domain": "network",
"rules": [
{
"actions": [
"connect:tcp",
"connect:udp"
],
"decision": "allow",
"id": "rule_06evsm9qjm1pdsk0a8nkfaxy7jna",
"name": "allow research mirrors",
"resources": [
"research.mitre.org",
"cve.mitre.org"
]
}
]
},
"created_at": "2026-04-22T00:00:00Z",
"id": "pol_06evsmp24r1pg71cm8500546pkbn",
"name": "Security Research — hardened",
"org": "my-org",
"scope": {
"teams": [
"d290f1ee-6c54-4b01-90e6-d701748f0851"
]
},
"updated_at": "2026-04-22T00:00:00Z"
}
}▸ 400 Bad request
Schema: Error
{
"error": {
"code": "invalid_argument",
"message": "name is required"
}
}▸ 401 Missing or invalid credentials
Schema: Error
{
"error": {
"code": "unauthenticated",
"message": "unauthenticated"
}
}▸ 403 Caller lacks the required permission for this org, or the org is not entitled to use governance.
Schema: Error
{
"error": {
"code": "permission_denied",
"message": "permission denied"
}
}▸ 404 Not found
Schema: Error
{
"error": {
"code": "not_found",
"message": "policy not found"
}
}▸ 409 Conflict
Schema: Error
{
"error": {
"code": "conflict",
"message": "policy name already in use"
}
}▸ 500 Internal server error
Schema: Error
{
"error": {
"code": "internal",
"message": "internal error"
}
}/orgs/{org_name}/governance/policies/{policy_id}updated_at is unchanged by the deletion.
Changes may take up to five minutes to reach developer machines.Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
org_name | path | string | yes | Docker Hub organization name. |
policy_id | path | string | yes | Unique policy identifier. |
Responses
▸ 200 Policy deleted, returns the deleted policy.
Schema: DeletePolicyResponse
{
"deleted": {
"allowlist_v0": {
"domain": "network",
"rules": [
{
"actions": [
"connect:tcp",
"connect:udp"
],
"decision": "allow",
"id": "rule_06evsm9qjm1pdsk0a8nkfaxy7jna",
"name": "allow research mirrors",
"resources": [
"research.mitre.org",
"cve.mitre.org"
]
}
]
},
"created_at": "2026-04-22T00:00:00Z",
"id": "pol_06evsmp24r1pg71cm8500546pkbn",
"name": "Security Research — hardened",
"org": "my-org",
"scope": {
"teams": [
"d290f1ee-6c54-4b01-90e6-d701748f0851"
]
},
"updated_at": "2026-04-22T00:00:00Z"
}
}▸ 401 Missing or invalid credentials
Schema: Error
{
"error": {
"code": "unauthenticated",
"message": "unauthenticated"
}
}▸ 403 Caller lacks the required permission for this org, or the org is not entitled to use governance.
Schema: Error
{
"error": {
"code": "permission_denied",
"message": "permission denied"
}
}▸ 404 Not found
Schema: Error
{
"error": {
"code": "not_found",
"message": "policy not found"
}
}▸ 500 Internal server error
Schema: Error
{
"error": {
"code": "internal",
"message": "internal error"
}
}Rules
Rule management within an allowlist policy
/orgs/{org_name}/governance/policies/{policy_id}/rulesAdds a rule to the policy's rule set. All rules in a policy must share the same domain (network or filesystem); mixing domains is rejected.
Network actions: connect:tcp, connect:udp. Resources are
hostnames (for example, example.com), wildcard subdomains (*.example.com
for one level, **.example.com for any depth), hostnames with an optional
port (for example, example.com:443), or CIDRs in IPv4 or IPv6 notation
(for example, 10.0.0.0/8 or 2001:db8::/32).
Filesystem actions: read, write. Resources are paths (for example,
/data). Use * to match within a single path segment and ** to match
recursively across segments (for example, /data/**).
Changes may take up to five minutes to reach developer machines.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
org_name | path | string | yes | Docker Hub organization name. |
policy_id | path | string | yes | Unique policy identifier. |
Request body
Rule definition including actions, resources, and decision.
Content type:
application/json
Schema: CreateRuleRequest
{
"actions": [
"read",
"write"
],
"decision": "allow",
"name": "allow data directory",
"resources": [
"/data"
]
}{
"actions": [
"connect:tcp",
"connect:udp"
],
"decision": "allow",
"name": "allow research mirrors",
"resources": [
"research.mitre.org",
"cve.mitre.org"
]
}Responses
▸ 201 Rule created and added to the policy's rule set.
Schema: Rule
{
"actions": [
"read",
"write"
],
"decision": "allow",
"id": "rule_07fwtnr0kn2qetl1b9olfbyz8kob",
"name": "allow data directory",
"resources": [
"/data"
]
}{
"actions": [
"connect:tcp",
"connect:udp"
],
"decision": "allow",
"id": "rule_06evsm9qjm1pdsk0a8nkfaxy7jna",
"name": "allow research mirrors",
"resources": [
"research.mitre.org",
"cve.mitre.org"
]
}▸ 400 Bad request
Schema: Error
{
"error": {
"code": "invalid_argument",
"message": "name is required"
}
}▸ 401 Missing or invalid credentials
Schema: Error
{
"error": {
"code": "unauthenticated",
"message": "unauthenticated"
}
}▸ 403 Caller lacks the required permission for this org, or the org is not entitled to use governance.
Schema: Error
{
"error": {
"code": "permission_denied",
"message": "permission denied"
}
}▸ 404 Not found
Schema: Error
{
"error": {
"code": "not_found",
"message": "policy not found"
}
}▸ 409 Conflict
Schema: Error
{
"error": {
"code": "conflict",
"message": "policy name already in use"
}
}▸ 500 Internal server error
Schema: Error
{
"error": {
"code": "internal",
"message": "internal error"
}
}/orgs/{org_name}/governance/policies/{policy_id}/rules/{rule_id}Partially updates a rule. Only fields present in the request body are updated; absent fields are left unchanged. Returns the rule in both its old and new states.
Changing actions across domains (for example, from network actions to
filesystem actions) is rejected. Changes may take up to five minutes to
reach developer machines.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
org_name | path | string | yes | Docker Hub organization name. |
policy_id | path | string | yes | Unique policy identifier. |
rule_id | path | string | yes | Unique rule identifier within the policy. |
Request body
Fields to update. Absent fields are left unchanged.
Content type:
application/json
Schema: UpdateRuleRequest
{
"resources": [
"research.mitre.org"
]
}Responses
▸ 200 Rule updated, returns old and new states.
Schema: UpdateRuleResponse
{
"new": {
"actions": [
"connect:tcp",
"connect:udp"
],
"decision": "allow",
"id": "rule_06evsm9qjm1pdsk0a8nkfaxy7jna",
"name": "allow research mirrors",
"resources": [
"research.mitre.org"
]
},
"old": {
"actions": [
"connect:tcp",
"connect:udp"
],
"decision": "allow",
"id": "rule_06evsm9qjm1pdsk0a8nkfaxy7jna",
"name": "allow research mirrors",
"resources": [
"research.mitre.org",
"cve.mitre.org"
]
}
}▸ 400 Bad request
Schema: Error
{
"error": {
"code": "invalid_argument",
"message": "name is required"
}
}▸ 401 Missing or invalid credentials
Schema: Error
{
"error": {
"code": "unauthenticated",
"message": "unauthenticated"
}
}▸ 403 Caller lacks the required permission for this org, or the org is not entitled to use governance.
Schema: Error
{
"error": {
"code": "permission_denied",
"message": "permission denied"
}
}▸ 404 Not found
Schema: Error
{
"error": {
"code": "not_found",
"message": "policy not found"
}
}▸ 409 Conflict
Schema: Error
{
"error": {
"code": "conflict",
"message": "policy name already in use"
}
}▸ 500 Internal server error
Schema: Error
{
"error": {
"code": "internal",
"message": "internal error"
}
}/orgs/{org_name}/governance/policies/{policy_id}/rules/{rule_id}Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
org_name | path | string | yes | Docker Hub organization name. |
policy_id | path | string | yes | Unique policy identifier. |
rule_id | path | string | yes | Unique rule identifier within the policy. |
Responses
▸ 200 Rule deleted, returns the deleted rule.
Schema: DeleteRuleResponse
{
"deleted": {
"actions": [
"connect:tcp",
"connect:udp"
],
"decision": "allow",
"id": "rule_06evsm9qjm1pdsk0a8nkfaxy7jna",
"name": "allow research mirrors",
"resources": [
"research.mitre.org",
"cve.mitre.org"
]
}
}▸ 401 Missing or invalid credentials
Schema: Error
{
"error": {
"code": "unauthenticated",
"message": "unauthenticated"
}
}▸ 403 Caller lacks the required permission for this org, or the org is not entitled to use governance.
Schema: Error
{
"error": {
"code": "permission_denied",
"message": "permission denied"
}
}▸ 404 Not found
Schema: Error
{
"error": {
"code": "not_found",
"message": "policy not found"
}
}▸ 500 Internal server error
Schema: Error
{
"error": {
"code": "internal",
"message": "internal error"
}
}Schemas
AllowlistV0
PolicySummary.type is allowlist_v0; omitted when the
policy has no rules yet. All rules in an allowlist share the same domain.
All rules are evaluated on every request: deny always wins over allow.| Property | Type | Required | Description |
|---|---|---|---|
domain | string | no | The access-control domain shared by all rules in this allowlist. Derived from rule actions: network actions (connect:tcp, connect:udp) produce network; filesystem actions (read, write) produce filesystem. Present when rules is non-empty; absent when the allowlist has no rules. |
rules | array<Rule> | yes |
CreatePolicyRequest
| Property | Type | Required | Description |
|---|---|---|---|
name | string | yes | Policy name, unique within the organization. |
scope | Scope | no | Restricts the policy to specific teams. An empty or absent list means the policy applies org-wide. |
CreateRuleRequest
| Property | Type | Required | Description |
|---|---|---|---|
actions | RuleActions | yes | Network actions: connect:tcp, connect:udp. Filesystem actions: read, write. All actions in a rule must belong to the same domain; mixing network and filesystem actions in one rule is rejected. |
decision | RuleDecision | yes | Outcome applied when this rule matches a request. deny always wins: if any rule in the policy matches with decision: deny, the request is denied even if other rules match with decision: allow. |
name | string | yes | Human-readable label for the rule. |
resources | RuleResources | yes | Network domain: hostnames (for example, example.com), wildcard subdomains (*.example.com or **.example.com), hostnames with port (for example, example.com:443), or CIDRs in IPv4 or IPv6 notation (for example, 10.0.0.0/8 or 2001:db8::/32). Filesystem domain: paths (for example, /data); * matches within one path segment, ** matches recursively (for example, /data/**). |
DeletePolicyResponse
| Property | Type | Required | Description |
|---|---|---|---|
deleted | Policy | yes | Full policy representation including the allowlist rule set. |
DeleteRuleResponse
| Property | Type | Required | Description |
|---|---|---|---|
deleted | Rule | yes | A single allow or deny rule within an allowlist policy. |
Error
| Property | Type | Required | Description |
|---|---|---|---|
error | object | yes | Error detail. |
Policy
| Property | Type | Required | Description |
|---|---|---|---|
allowlist_v0 | AllowlistV0 | no | Network or filesystem allowlist containing a list of rules. Present on
Policy when PolicySummary.type is allowlist_v0; omitted when the
policy has no rules yet. All rules in an allowlist share the same domain.
All rules are evaluated on every request: deny always wins over allow. |
created_at | string | yes | |
id | string | yes | |
name | string | yes | Human-readable label, unique within the organization. |
org | string | yes | |
scope | Scope | yes | Restricts the policy to specific teams. An empty or absent list means the policy applies org-wide. |
updated_at | string | yes |
PolicySummary
| Property | Type | Required | Description |
|---|---|---|---|
created_at | string | yes | |
id | string | yes | |
name | string | yes | Human-readable label, unique within the organization. |
org | string | yes | |
scope | Scope | yes | Restricts the policy to specific teams. An empty or absent list means the policy applies org-wide. |
type | string | yes | Identifies the rule-set format. Always allowlist_v0, corresponding to the allowlist_v0 property on the full Policy object. |
updated_at | string | yes |
Rule
| Property | Type | Required | Description |
|---|---|---|---|
actions | RuleActions | yes | Network actions: connect:tcp, connect:udp. Filesystem actions: read, write. All actions in a rule must belong to the same domain; mixing network and filesystem actions in one rule is rejected. |
decision | RuleDecision | yes | Outcome applied when this rule matches a request. deny always wins: if any rule in the policy matches with decision: deny, the request is denied even if other rules match with decision: allow. |
id | string | yes | |
name | string | yes | Human-readable label for the rule. |
resources | RuleResources | yes | Network domain: hostnames (for example, example.com), wildcard subdomains (*.example.com or **.example.com), hostnames with port (for example, example.com:443), or CIDRs in IPv4 or IPv6 notation (for example, 10.0.0.0/8 or 2001:db8::/32). Filesystem domain: paths (for example, /data); * matches within one path segment, ** matches recursively (for example, /data/**). |
RuleActions
connect:tcp, connect:udp. Filesystem actions: read, write. All actions in a rule must belong to the same domain; mixing network and filesystem actions in one rule is rejected.Items: string
RuleDecision
deny always wins: if any rule in the policy matches with decision: deny, the request is denied even if other rules match with decision: allow.Enum:allow,deny
RuleResources
example.com), wildcard subdomains (*.example.com or **.example.com), hostnames with port (for example, example.com:443), or CIDRs in IPv4 or IPv6 notation (for example, 10.0.0.0/8 or 2001:db8::/32). Filesystem domain: paths (for example, /data); * matches within one path segment, ** matches recursively (for example, /data/**).Items: string
Scope
| Property | Type | Required | Description |
|---|---|---|---|
teams | array<string> | no | Team UUIDs the policy applies to. Each must be a valid team in the org. |
ScopePatch
| Property | Type | Required | Description |
|---|---|---|---|
teams | array<string> | no |
UpdatePolicyRequest
| Property | Type | Required | Description |
|---|---|---|---|
name | string | no | Policy name, unique within the organization. |
scope | ScopePatch | no | Per-sub-field patch of a policy's scope. An omitted sub-field is left unchanged; a present list replaces that dimension, and an empty list clears it (making the policy org-wide for that dimension). |
UpdatePolicyResponse
| Property | Type | Required | Description |
|---|---|---|---|
new | Policy | yes | Full policy representation including the allowlist rule set. |
old | Policy | yes | Full policy representation including the allowlist rule set. |
UpdateRuleRequest
| Property | Type | Required | Description |
|---|---|---|---|
actions | RuleActions | no | Network actions: connect:tcp, connect:udp. Filesystem actions: read, write. All actions in a rule must belong to the same domain; mixing network and filesystem actions in one rule is rejected. |
decision | RuleDecision | no | Outcome applied when this rule matches a request. deny always wins: if any rule in the policy matches with decision: deny, the request is denied even if other rules match with decision: allow. |
name | string | no | Human-readable label for the rule. |
resources | RuleResources | no | Network domain: hostnames (for example, example.com), wildcard subdomains (*.example.com or **.example.com), hostnames with port (for example, example.com:443), or CIDRs in IPv4 or IPv6 notation (for example, 10.0.0.0/8 or 2001:db8::/32). Filesystem domain: paths (for example, /data); * matches within one path segment, ** matches recursively (for example, /data/**). |