The Partner plan
Your customers approve. Your rules do the rest.
Your agent asks before it acts. A $42 refund just runs. A $4,200 refund asks your customer first, on their phone.
How do I add human approval to an AI product my customers use?
Pushary is a managed authorization layer built for companies shipping an AI agent to their own customers. One call, authorize(), evaluates your policy before the action runs and settles it three ways: allow it, deny it, or reach the person whose money or data it touches. Rules read the action's parameters, so "refunds at or above $1,000 need a human" is a row you edit rather than code you ship. With an explicit allow rule for low-value refunds, a $42 refund runs without paging anyone. Anything your rules do not name goes to a person, so a missing rule and an empty policy both fail safe. Every verdict is written to an audit trail naming the rule or the human that settled it. You do not build the policy evaluator, the delivery pipeline, the durable wait, the timeout policy, or the ledger.
The moment
Your agent is about to spend someone else's money
Most of what your agent does can be undone, so let it run. Then it reaches a refund, a deletion, a payment. Someone should say yes to that first, and it should be the customer whose money it is, not you.
Three answers, and you decide which one
A rule can read the amount, so you get "refunds over $1,000 need approval" instead of "all refunds need approval".
refund.create amount < 100 allow
refund.create amount >= 1000 require_approval
refund.create amount >= 10000 deny$42 runs on its own. $4,200 asks your customer first. $40,000 never happens. Anything you forgot to write a rule for asks a person, so a gap is never a yes.
POST /api/v1/server/authorization-rules
{
"toolPattern": "refund.create",
"effect": "require_approval",
"conditions": [
{ "parameter": "amount", "operator": "gte", "value": 1000 }
]
}- allow
- A rule of yours names this action and permits it. The agent proceeds, nobody is paged, and the row records which rule decided.
- deny
- A rule refuses it. The agent stops and gets a reason back in plain text, so the model can act on it instead of retrying the same action.
- requires_human
- Either a rule of yours asks for a person, or no rule names the action at all. Both go to the person whose money or data it touches. An empty policy and a missing parameter land here too, so a rule you have not written yet asks rather than allows.
The strictest rule wins, so the order you write them in never changes the answer. The rule decides whether to ask. You decide who gets asked.
The call
Two calls, and most actions never reach a person
The same code works for one customer or a hundred thousand. You point at them with the id you already have, and only when your rules cannot settle it themselves.
The rules above decided this one. The rest of your code is unchanged.
import { createPusharyServer } from "@pushary/server"
const px = createPusharyServer({ apiKey: process.env.PUSHARY_API_KEY! })
// In your onboarding flow, show this link to the signed-in customer.
// They must open it and connect the app or a supported browser.
const { universalLink } = await px.enroll(customer.id)
// Rules answer first. This one is over your $1,000 threshold.
const decision = await px.authorize({
toolName: "refund.create",
toolTarget: "order_4471",
externalId: customer.id,
parameters: { amount: 4200 },
question: "Approve a $4,200 refund for order #4471?",
})
if (!decision.approved) throw new Error(decision.reason)
await issueRefund()You always get the same answer back
Three outcomes, one shape. Check whether it was approved and carry on. There is no webhook to catch later.
// $42. Your rule allowed it. Your customer was never contacted.
{ approved: true, resolvedBy: "policy", reason: "Allowed by policy rule refund.create." }
// $4,200. Your require_approval rule sent it to your customer. They tapped Approve.
{ approved: true, resolvedBy: "human", reason: "A person approved it." }
// $4,200, and nobody answered inside the window.
{ approved: false, resolvedBy: "human", reason: "Nobody answered, so this was not approved." }A timeout is a denial, not a silence you have to interpret. Your agent gets approved: false and a reason it can log, and the refund does not happen. An action your rules never named comes back the same way. No rule settled it, so a person did, and resolvedBy reads "human".
You can build this. Here is what it is.
None of these parts is hard on its own. Together they are a distributed systems project sitting in the middle of the product you meant to be shipping.
- Deciding
- A policy evaluator that reads an action's parameters, resolves conflicting rules the same way every time, treats a parameter it cannot read as a reason to ask rather than a reason to pass, and does not need a deploy when a threshold moves.
- Reaching the person
- A delivery path to a phone that works when the person is not at a desk, with a fallback when the first channel fails.
- Connecting a user
- An enrollment flow for someone who has no account with you, has never heard of your vendor, and will give it one tap and no more.
- Waiting
- A wait that holds across a deploy or a crash, rather than an in-memory promise that dies with the process.
- Timing out
- A timeout that denies instead of assuming yes, and a way to tell the two apart afterwards.
- The record
- A queryable store of who was asked, what they saw, what they chose, and when.
- The page they answer on
- A decide surface that carries your brand, because it is your customer looking at it.
Built for your customer, not your engineer
The person tapping approve has never heard of Pushary, and never has to.
Your users, not just you
The externalId is your own id for the end-user. Give them an enrollment link to connect the Pushary app or a supported browser. No account, no key, and no bill on their side. The link opens the Pushary app, which is what puts Approve and Deny on the lock screen.
Durable waits that fail closed
The SDK returns approved: false if its wait ends without approval. The decision can still be pending. Save its ID and proposed action in your workflow so a restarted worker can read the result and run only after explicit approval.
A decide page under your brand
The person answering is your customer, so the page they land on carries your product name and your logo. Turn off the Pushary line in settings and our name is not on it at all. They never see a Pushary login, and they never get a Pushary bill.
Signed webhooks and an exportable ledger
Every decision is written to a durable ledger you can query and export, and resolved decisions post a signed webhook to your callback URL. The record of who approved what is there without you keeping it.
Who embeds this
Where the approver is somebody else
The rules and the SDK do not change. What changes is whose phone the exceptions land on.
You ship an AI agent to customers
Your product takes actions on a customer's behalf, and some of those actions should not happen without that specific customer saying yes. Refunds, outbound messages, record deletions, anything that moves money. Pushary asks the person whose data or money is on the line, and returns their answer to your agent.
You build agents for clients
Every client build repeats the same approval plumbing, and it is never the part you quoted for. Embedding Pushary once takes it off the estimate for every project after this one. One Partner plan covers one workspace, so several client workspaces is a different shape and we will price it with you.
You run a platform other people build on
Your users are building agents that need a human step, and right now they each solve it badly on their own. A Pushary integration gives all of them the same approval primitive without you building one into the platform.
One product, your own customers: this is the plan. Several client workspaces, or a platform other people build on, is a different shape. Tell us the shape and we will price it with you.
Pricing
One plan for embedding it
One price for putting this inside a product your own customers use.
The standard price for the Partner plan is $299 a month. Accounts that start now keep $99 for as long as they stay subscribed.
Scale
- Connected end-users
- 25,000
- Notifications a month
- 100,000
- Team members
- 10
- Decision history
- 365 days
Included
- Embed in your own product
- Whitelabel decide page
- Signed webhooks
- Server and Python SDKs
- Exportable decisions ledger
Questions, answered
How do I add human approval to an AI product my customers use?
Do my end-users need a Pushary account or an app?
Who decides which of my customers gets asked?
Does this mean more interruptions for my customers?
How is this different from a notification API like Knock or Novu?
How is this different from HumanLayer?
What happens if the person never answers?
What is included in the $99 Partner plan?
Which frameworks does this work with?
I build agents for several clients. Do I need one plan each?
Does this cover the EU AI Act human oversight requirement?
Most actions should never reach a person.
Write the rules for the ones that should. Your agent gets allow, deny, or the answer of the customer whose money it is, and every verdict is on the record.