Skip to content

Approve a pending policy entry

POST
/api/policy-entries/{entryId}/approve

Approves a policy that awaits review, with status pending_review or proposed. An approved policy is applied by the assistant. The edits in the body are approved in place of the policy’s own fields, and the fields not sent stay as they are. A proposal that changes an existing policy is applied to that policy, which takes the proposal’s topic, rule text and conditions, with the edits in place of the ones sent. Approving a policy that is already approved answers with it unchanged.

entryId
required
string format: uuid

The unique identifier of the policy entry to approve.

Optional. Edits to a policy that awaits review (proposed or pending_review), approved in place of the policy’s own fields; the fields not sent stay as they are. On a proposal that changes an existing policy, that policy takes the proposal’s topic, rule text and conditions, with the edits in place of the ones sent.

object
topic

The topic to approve, in place of the policy’s own.

string
>= 1 characters
ruleText

The rule text to approve, in place of the policy’s own.

string
>= 1 characters
conditions

The conditions to approve, in place of the policy’s own.

object
key
additional properties
expectedTargetVersionId

After a 409, the publishedVersionId of the returned currentTarget: the version of the existing policy the proposal is approved onto.

string format: uuid

The approved policy. For a proposal that changes an existing policy, the policy it changed.

A policy entry defines a rule that governs how the AI should behave in specific situations. Unlike KB entries (which provide factual answers), policies specify constraints, guardrails, and behavioral guidelines. For example, ‘Never offer more than 10% discount without manager approval’ or ‘Always ask for an order number before looking up shipping status’. Policies can be created manually or proposed by the learning loop.

object
id
required

Unique identifier for the policy entry.

string format: uuid
Example
pe1a2b3c-5678-9abc-def0-1234567890ab
tenantId
required

The tenant this policy belongs to.

string format: uuid
Example
a0b1c2d3-4567-89ab-cdef-0123456789ab
workspaceId
required

The workspace this policy is scoped to.

string format: uuid
Example
w1a2b3c4-5678-9abc-def0-1234567890ab
topic
required

The topic or domain this policy applies to. Used by the AI to determine which policies are relevant to the current conversation.

string
Example
discount_authorization
ruleText
required

The policy rule in natural language. This is the instruction the AI follows.

string
Example
Never offer a discount above 10% without creating an attention item for manager approval. For discounts up to 10%, apply automatically if the customer has placed 3 or more orders.
conditions

Optional structured data stored with the policy, as free-form JSON. The Policy Agent receives it together with the rule text when it retrieves the policy.

object | null
Example
{
"min_order_value": 500,
"customer_tier": "gold"
}
sourceType
required

How the policy came to be. manual is a policy written by a person, approved when it is created. extracted is a proposal the learning loop drafted from a resolved conversation. The API stores the value sent, and a policy created with a value other than manual starts as pending_review.

string
Example
manual
confidence

Confidence score between 0 and 1, set by the learning loop when proposing policies. Null for manually created policies.

number | null
Example
0.85
status
required

Where the policy stands, with the values of a knowledge base entry. approved: in use, the assistant applies it. pending_review: created for review, through the API with a sourceType other than manual; it is not applied until it is approved. proposed: drafted by oHallo, for example by the learning loop from a resolved conversation; it is not applied until it is approved, and a proposal that changes an existing policy is applied to that policy when it is approved. rejected: declined in review. archived: no longer in use, kept for the record.

string
Allowed values: pending_review approved rejected archived proposed
Example
approved
createdAt
required

Timestamp when the policy was created.

string format: date-time
Example
2026-02-05T09:00:00.000Z
updatedAt
required

Timestamp when the policy was last updated.

string format: date-time
Example
2026-03-18T11:30:00.000Z

The policy was rejected before this approval (error: Entry is no longer awaiting review).

Standard error response returned by all endpoints on failure.

object
error
required

A human-readable error message describing what went wrong.

string
Example
Conversation not found
code

A machine-readable reason on some refusals, for example ‘key_lock’ when an API key’s brand or workspace restriction does not cover the action.

string
Example
key_lock
missing_scopes

On a 403 for an API key without a scope the endpoint requires: the scopes the key lacks.

Array<string>
Example
[
"mcp:write"
]
entryId

On a 409 with code duplicate_question or duplicate_rule_text: the knowledge base entry or policy that already holds the question or rule text.

string format: uuid
Example
11223344-5566-4788-99aa-bbccddeeff00
connectionId

On a 422 about one MCP connection a request names, from an assignment or an agent create or update (a connection that does not exist, one listed twice, or one that does not declare a tool named): the connection, as the request named it.

string
undeclaredTools

On the same 422: the tool names the connection does not declare.

Array<string>
Example
[
"get_orders"
]
declaredTools

On the same 422: the tools the connection declares.

Array<string>
Example
[
"get_order",
"search_orders"
]

No policy entry exists with the given ID in the authenticated tenant.

Standard error response returned by all endpoints on failure.

object
error
required

A human-readable error message describing what went wrong.

string
Example
Conversation not found
code

A machine-readable reason on some refusals, for example ‘key_lock’ when an API key’s brand or workspace restriction does not cover the action.

string
Example
key_lock
missing_scopes

On a 403 for an API key without a scope the endpoint requires: the scopes the key lacks.

Array<string>
Example
[
"mcp:write"
]
entryId

On a 409 with code duplicate_question or duplicate_rule_text: the knowledge base entry or policy that already holds the question or rule text.

string format: uuid
Example
11223344-5566-4788-99aa-bbccddeeff00
connectionId

On a 422 about one MCP connection a request names, from an assignment or an agent create or update (a connection that does not exist, one listed twice, or one that does not declare a tool named): the connection, as the request named it.

string
undeclaredTools

On the same 422: the tool names the connection does not declare.

Array<string>
Example
[
"get_orders"
]
declaredTools

On the same 422: the tools the connection declares.

Array<string>
Example
[
"get_order",
"search_orders"
]

The existing policy this proposal changes was edited after the proposal was written. The body carries currentTarget, the policy as it stands. To approve the proposal onto it, send the approval again with expectedTargetVersionId set to currentTarget.publishedVersionId. A 409 with code duplicate_rule_text means the approval would give the policy a rule text another policy of the workspace has; entryId names that policy.

Standard error response returned by all endpoints on failure.

object
error
required

A human-readable error message describing what went wrong.

string
Example
Conversation not found
code

A machine-readable reason on some refusals, for example ‘key_lock’ when an API key’s brand or workspace restriction does not cover the action.

string
Example
key_lock
missing_scopes

On a 403 for an API key without a scope the endpoint requires: the scopes the key lacks.

Array<string>
Example
[
"mcp:write"
]
entryId

On a 409 with code duplicate_question or duplicate_rule_text: the knowledge base entry or policy that already holds the question or rule text.

string format: uuid
Example
11223344-5566-4788-99aa-bbccddeeff00
connectionId

On a 422 about one MCP connection a request names, from an assignment or an agent create or update (a connection that does not exist, one listed twice, or one that does not declare a tool named): the connection, as the request named it.

string
undeclaredTools

On the same 422: the tool names the connection does not declare.

Array<string>
Example
[
"get_orders"
]
declaredTools

On the same 422: the tools the connection declares.

Array<string>
Example
[
"get_order",
"search_orders"
]