Policies
How Veriticity decides what an AI agent may buy. Spending limits, merchant allow and block lists, budget windows, approval thresholds, and why policies are authored by people.
A policy is the set of rules the Trust Engine evaluates a purchase against. Spending limits, approval thresholds, merchant lists and budget windows, attached to an organisation or to particular agents.
Policies are written by people#
There is no API for creating, editing, activating or archiving a policy, and there will not be one. Every credential of every kind is refused with 403 api_key_not_permitted.
If you receive api_key_not_permitted, no other credential will work. Do not go looking for one.
What a policy contains#
| Field | Meaning |
|---|---|
scopeType | ORGANIZATION governs every agent; AGENT governs the ones in agentIds. |
status | ACTIVE, DISABLED or ARCHIVED. |
inForce | Whether the engine is actually reading it right now. Not the same as having an active version — see below. |
activeVersion | The version the engine evaluates against, or null. |
What a version contains#
Rules#
| Combination | What it does |
|---|---|
AMOUNT_LIMIT + BLOCK | A single-purchase maximum. Anything above it is refused outright. |
AMOUNT_LIMIT + REQUIRE_APPROVAL | An approval threshold. Above it, a person is asked and the budget is held. |
SPEND_LIMIT + BLOCK, period DAY or MONTH | A budget. Total spending in the window is capped. |
SPEND_LIMIT + REQUIRE_APPROVAL | A budget that escalates rather than refusing once crossed. |
Merchant lists#
ALLOW and BLOCK. A block list refuses what is on it; an allow list refuses everything that is not on it. Merchant names are normalised into a merchantKey for matching, so “Acme Cloud” and “acme cloud” match. Domains are recorded as evidence and are never matched on.
Versions and lifecycle#
Policies are versioned, and versions are immutable once active. A decision records which version it was evaluated against, so a purchase from March can be explained against the rules that were in force in March rather than today’s.
DRAFT— editable, not enforced. A policy may have one.ACTIVE— enforced. Exactly one per policy.ARCHIVED— superseded, kept for evidence.
Budget windows#
A SPEND_LIMIT creates a window — a day or a month — resolved against the organisation’s timezone rather than the server’s or the caller’s. A daily limit resets at midnight where the organisation is.
A window tracks three separate quantities:
| Quantity | Meaning |
|---|---|
heldMinor | Reserved by purchases waiting on a person. |
committedMinor | Spent by purchases that were approved. |
openingBalanceMinor | Reconciled spend the window’s own reservations do not account for. |
A simulation returns all three plus what the purchase would add, which is the honest way to answer “how much is left”. Subscribe to budget.threshold_reached and budget.exhausted on webhooks to be told rather than having to poll.
Currency scope#
A version declares which currencies it covers. Veriticity performs no currency conversion, so a purchase in a currency no applicable policy covers is refused with CURRENCY_NOT_COVERED rather than converted at a rate nobody agreed to.
A simulation lists the policies excluded for exactly this reason under policiesExcludedByCurrencyScope, which is what makes a NO_APPLICABLE_POLICY answer actionable.
Reading policies over the API#
Three read endpoints, all organisation-scoped API keys only:
GET /v1/policies— filter with?statusand?search, page with?pageand?pageSize.GET /v1/policies/{id}GET /v1/policies/{id}/versions/{versionId}
An agent-bound credential is refused. The constraints being drawn up for an agent are the authoring side’s business — an agent learns what it may spend by asking, through a simulation, rather than by reading the rules.
Testing a change before it is live#
Two endpoints help before an activation:
Validate#
Runs activation’s own check as a dry run. It answers 200 even when the draft is unacceptable — you asked a question and got an answer.
budgetImpact is empty in the ordinary case. A non-empty one means activating would start a limit from a total that already includes spending nobody reserved against — worth looking at before you activate.
Simulate#
POST /v1/simulations/draft-policy asks what a draft would decide about a specific purchase. POST /v1/simulations/policy-version asks the same of an active or archived version, exactly as it was frozen — which is how you explain a decision that was made months ago.