Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.getovra.com/llms.txt

Use this file to discover all available pages before exploring further.

An intent is a declaration of what an agent wants to pay for, how much, and to whom. The policy engine and risk engine evaluate every intent before it can settle. requireIntent is one of the sacred invariants — never silently dropped, never bypassed.

The intent model

FieldDescription
idint_*
agentIdOwning agent
cardId / cardNameWhich card to charge — exactly one of these
purposeFree text — surfaces in audit and dashboard
expectedAmountEurosOptional but strongly recommended
expectedMerchantOptional but strongly recommended
recurringOptional — cadence (daily/weekly/monthly/yearly) + tolerance windows
clientIntentIdOptional client-side dedupe key
ttlMinutesDefault 24h, max 30 days (43200)
statusFSM (below)

Lifecycle (FSM)

pending_approval → approved | denied | expired | cancelled
approved         → completed | failed | expired | cancelled
denied | completed | failed | expired | cancelled = terminal
StatusMeaning
pending_approvalPolicy or risk requires a human
approvedAuto-approved or human-approved; ready to pay
completedSuccessfully settled
deniedRejected by policy or risk
failedSettlement failed downstream
expiredTTL passed
cancelledOwner cancelled before settlement

Create an intent

curl -X POST https://api.getovra.com/intents \
  -H "Authorization: Bearer $OVRA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "agentId": "ag_...",
    "cardName": "subscriptions",
    "purpose": "Renew Hetzner monthly",
    "expectedAmountEuros": 4.51,
    "expectedMerchant": "hetzner.com",
    "ttlMinutes": 60
  }'
Response:
{
  "id": "int_...",
  "status": "approved",
  "expiresAt": "2026-04-20T11:00:00Z",
  "agentId": "ag_...",
  "cardId": "ca_...",
  "expectedAmountEuros": 4.51,
  "expectedMerchant": "hetzner.com"
}
If status is pending_approval, approve via dashboard or API.

Approve / deny

# Approve
curl -X POST https://api.getovra.com/intents/int_.../approve \
  -H "Authorization: Bearer $OVRA_API_KEY"

# Deny
curl -X POST https://api.getovra.com/intents/int_.../deny \
  -H "Authorization: Bearer $OVRA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "reason": "Out of budget for the quarter" }'

Recurring intents

A single intent can authorize a series of charges, with tolerance windows on amount and time:
{
  "agentId": "ag_...",
  "cardName": "subscriptions",
  "purpose": "Hetzner — monthly server",
  "expectedAmountEuros": 4.51,
  "expectedMerchant": "hetzner.com",
  "recurring": {
    "cadence": "monthly",
    "windowStartDaysBefore": 3,
    "windowEndDaysAfter": 2,
    "amountTolerancePercent": 10,
    "merchantMatch": true
  }
}

Verification (post-settlement)

After a charge completes you can record the actual amount and merchant for reconciliation:
curl -X POST https://api.getovra.com/intents/int_.../verify \
  -H "Authorization: Bearer $OVRA_API_KEY" \
  -d '{
    "actualAmountEuros": 4.51,
    "actualMerchant": "hetzner.com"
  }'
If actualAmountEuros deviates from expectedAmountEuros beyond the policy’s amountTolerancePercent, the intent is flagged.

Webhooks

EventWhen
intent.createdIntent insert
intent.approvedStatus flip to approved
intent.deniedPolicy or risk rejected
intent.expiredTTL hit
intent.cancelledOwner cancelled

Surfaces

SurfaceCapability
REST/intents, /intents/:id/{approve,deny,verify,cancel}
SDKovra.intents.*
MCPovra_intent (action: declare · get · cancel · verify)
Dashboard/dashboard/intents (list, drawer, approve/deny inline)

Next

Policies

The rules that drive approved vs pending_approval vs denied.

Pay

What happens after approved.

Transactions

The record a settled intent produces.

Webhooks

React to FSM transitions in real time.