Build approval flows with Nuvouch.
Nuvouch lets your app ask the user “Should this happen?” before any critical action executes. The docs use one simple model throughout:
Nuvouch is approval infrastructure for AI agent platforms, fintech and payment flows, dangerous API actions, and enterprise workflows. It is not payment processing, primary auth, OTP, or fraud scoring.
WHO → subject · WHERE → source · WHAT → action · AMOUNT → amount · DETAILS → details · TRIGGER → actor · RISK → risk · CHOICES → decisions · INTERNAL → metadata
Install Nuvouch on a trusted device to review approval requests during integration testing.
Approval Request Model
Build every request around four questions: who is this for, where did it come from, what is happening, and what will the user decide?
Keep the mental model simple. Use subject for the recipient, source for origin, action for the thing being approved, decisions for the buttons, and keep integrator-only data in metadata.
subject
Identifies the user who will receive the approval request.
subject: { id: "user_123" }source
Identifies where the request originated.
source: {
key: "stripe:acct_123",
name: "Stripe",
}keyis required and should be stable.nameis optional and used for display.
action
Describes what is about to happen.
action: {
type: "payment.authorization",
title: "Approve payment",
description: "Allow Billing Agent to charge $84.00",
}typeis machine-readable.titleis short.descriptionexplains the consequence.
amount
Used for financial requests and shown prominently in the UI.
amount: {
value: 84.0,
currency: "USD",
}details
Additional user-visible information, kept as an ordered list.
details: [
{ label: "Merchant", value: "OpenAI API" },
{ label: "Billing period", value: "April 2026" },
]- Safe to display.
- Keep entries ordered by importance.
actor
Who or what triggered the request.
actor: {
type: "ai_agent",
name: "Billing Agent",
}risk
Explains why the request may need attention.
risk: {
level: "medium",
signals: ["automated_action", "usage_threshold_exceeded"],
}levelis the summary.signalsare the reasons.
decisions
The choices shown to the user.
decisions: [
{ label: "Approve", value: "approve" },
{ label: "Deny", value: "deny" },
]metadata
Internal data for integrators. Returned in callbacks, not shown to users.
metadata: {
orderId: "ord_123",
}Quickstart
Integrating Nuvouch follows one simple pattern:
- Link the user once if you need a durable subject record.
- Create an approval request from your server.
- Wait for the signed callback from Nuvouch.
- Execute or block the action based on the user decision.
const approval = await nuvouch.approvals.create({
subject: { id: "user_123" },
source: {
key: "stripe:acct_123",
name: "Stripe",
},
action: {
type: "payment.authorization",
title: "Approve payment",
description: "Allow Billing Agent to charge $84.00",
},
amount: {
value: 84.0,
currency: "USD",
},
details: [
{ label: "Merchant", value: "OpenAI API" },
{ label: "Billing period", value: "April 2026" },
],
actor: {
type: "ai_agent",
name: "Billing Agent",
},
risk: {
level: "medium",
signals: ["automated_action", "usage_threshold_exceeded"],
},
decisions: [
{ label: "Approve", value: "approve" },
{ label: "Deny", value: "deny" },
],
metadata: {
orderId: "ord_123",
},
});
// wait for signed callback
// capture or block based on decisionWhat is Nuvouch?
Nuvouch is an approval infrastructure that sits between an action and its execution. It allows integrators like payment platforms, APIs, and services to request user approval before completing sensitive operations. Nuvouch is not the payer, the merchant, or the payment processor in those flows.
When should you use Nuvouch?
Use Nuvouch when your system needs to answer:
- Should this payment really happen?
- Should this AI agent be allowed to act?
- Should this request be trusted?
Approval before execution
Your system does not blindly execute actions. It asks the user first.
Real-world requests
Use the same shape for payments, login checks, and AI agent actions. Only the labels and signals change.
Payment approval
await nuvouch.approvals.create({
subject: { id: "user_123" },
source: { key: "stripe:acct_123", name: "Stripe" },
action: {
type: "payment.authorization",
title: "Approve payment",
description: "Allow Billing Agent to charge $84.00 for API usage",
},
amount: { value: 84.0, currency: "USD" },
details: [
{ label: "Merchant", value: "OpenAI API" },
{ label: "Billing period", value: "April 2026" },
],
actor: { type: "ai_agent", name: "Billing Agent" },
risk: {
level: "medium",
signals: ["automated_action", "high_amount"],
},
decisions: [
{ label: "Approve", value: "approve" },
{ label: "Deny", value: "deny" },
],
metadata: { orderId: "ord_123" },
});Login from new device
await nuvouch.approvals.create({
subject: { id: "user_123" },
source: { key: "auth:primary", name: "Auth Service" },
action: {
type: "login.verification",
title: "Approve login",
description: "Confirm sign-in from a new device in Lagos",
},
details: [
{ label: "Device", value: "MacBook Pro" },
{ label: "Location", value: "Lagos, Nigeria" },
{ label: "Time", value: "April 27, 2026 09:14 UTC" },
],
actor: { type: "system", name: "Authentication Service" },
risk: {
level: "high",
signals: ["new_device", "location_mismatch"],
},
decisions: [
{ label: "Approve", value: "approve" },
{ label: "Deny", value: "deny" },
],
metadata: { loginId: "login_123" },
});AI agent action
await nuvouch.approvals.create({
subject: { id: "user_123" },
source: { key: "agent:billing-bot", name: "Billing Bot" },
action: {
type: "agent.tool_call",
title: "Approve agent action",
description: "Allow Billing Bot to update the invoice and send a refund",
},
details: [
{ label: "Tool", value: "refunds.create" },
{ label: "Invoice", value: "inv_789" },
{ label: "Amount", value: "$24.00" },
],
actor: { type: "ai_agent", name: "Billing Bot" },
risk: {
level: "medium",
signals: ["automated_action", "sensitive_resource"],
},
decisions: [
{ label: "Approve", value: "approve" },
{ label: "Deny", value: "deny" },
],
metadata: { traceId: "trace_abc" },
});AI Agent
↓
Stripe (Source)
↓
Nuvouch (approval request)
↓
User Device (approve / deny)
↓
Nuvouch (signed callback)
↓
Stripe captures or blocks paymentHow Nuvouch works
- Action is initiated by an app, API, workflow, or AI agent.
- Your backend requests approval by sending the request to Nuvouch.
- Nuvouch notifies the user on their trusted device.
- The user approves or rejects in real time.
- Nuvouch returns the decision using a signed callback.
- You execute or block the action based on the callback.
Agent → Stripe → Nuvouch → User → Nuvouch → Stripe
How requests render on mobile
- Source shown at the top.
- Title shown as the heading.
- Description shown below the heading.
- Amount highlighted prominently.
- Details shown as an ordered list.
- Risk indicators shown near the decision area.
- Decisions shown as buttons.
Signal guidelines
Use short, consistent signals. Keep them stable so policy, analytics, and UI can rely on them.
automated_actionnew_devicelocation_mismatchhigh_amountsensitive_resource
Keep signals short. Keep them consistent.
Who are the actors?
Integrator
Your platform, such as a payment provider, API, or service.
- Create approval requests.
- Handle signed callbacks.
- Execute or block actions.
User
The end user with a Nuvouch account and trusted device.
- Receive approval requests.
- Approve or reject actions.
Good vs bad requests
Write titles and descriptions that explain the consequence, not just the existence of a prompt.
title: "Confirm"
description: "Approve this"title: "Approve payment"
description: "Allow Billing Agent to charge $84.00 for API usage"Why Nuvouch?
Without Nuvouch, actions happen automatically, users lose control, and fraud or mistakes become harder to prevent.
With Nuvouch, every sensitive action can be verified before execution, users stay in control, and systems become safer and more reliable.
Why not use OTP or 2FA alone?
OTP and traditional 2FA confirm access, but they usually do not describe the exact action being approved. Nuvouch is contextual: the user sees what is about to happen, who initiated it, and can approve or reject it before execution.
What if the user does nothing?
Approval requests should be treated as time-bound. If the user does not respond, the request can expire and your system should handle that outcome just like an approval or denial.
- Show pending state while the request is active.
- Handle expiry as a terminal outcome.
- Decide whether to retry, cancel, or ask the user again later.
Integration overview
- Create an approval request from your server.
- Wait for the signed callback.
- Verify the callback.
- Execute your business logic only after the verified decision.
Choose the right page
- Getting started covers provisioning, callback setup, first-run flow, and the retry contract around
externalRequestId. - HTTP API reference gives you the raw endpoints, request payloads, response shapes, and stable error codes.
- Node SDK reference covers the typed client, helper utilities, and server-side callback verification helpers.
- MCP + OAuth covers the official hosted MCP path for OAuth-capable agent clients.
- AI Agent Auth covers direct runtime pairing, scoped delegation, provider introspection, and CLI usage.
- Webhook reference documents signed delivery verification, deduplication, retry behavior, and lifecycle events.
- Integration guide walks through the end-to-end payment authorization flow from subject linking to verified execution.
Build with approval, not assumptions.
Start with an approval request, verify the signed callback, and make execution conditional on the user decision.