SDK — @pinti/guard
Policy enforcement + receipt audit for AI agent payments. Works with any payment rail — Stripe, MoonPay, crypto, or custom.
Installation
npm install @pinti/guardQuick Start
import { PintiGuard } from "@pinti/guard";
const pinti = new PintiGuard({
apiKey: process.env.PINTI_API_KEY!,
baseUrl: "https://pinti.ai", // optional, defaults to this
handleId: "clxyz...", // optional default handle
});Tip
authorize()
Evaluate a spend intent against your workspace policies. Returns the decision and a SAT (Spend Authorization Token) on ALLOW. Throws SpendDeniedError on DENY and ApprovalRequiredError on REQUIRE_APPROVAL.
const auth = await pinti.authorize({
amountMinor: 5000, // $50.00 in cents
currency: "usd",
merchant: "AWS",
agentId: "agent-1",
category: "cloud",
reason: "EC2 instance for data processing",
});
// auth.decision === "ALLOW"
// auth.sat === "eyJ..." — proof of authorization
// auth.spendRequestId === "cm..."submitReceipt()
After your payment executes (on any rail), submit a receipt to PINTI. PINTI compares the actual payment against the SAT claims and flags anomalies.
await pinti.submitReceipt({
spendRequestId: auth.spendRequestId,
sat: auth.sat,
railId: "stripe",
providerTransactionId: "ch_xxx",
actualAmountMinor: 5000,
actualCurrency: "usd",
});
// Returns: { receiptId, anomalyFlags, recorded }Note
guardedAction()
The recommended pattern. Wraps authorize → execute → receipt into a single call. If authorization fails, your payment callback is never called.
Stripe Example
import Stripe from "stripe";
const stripe = new Stripe(process.env.STRIPE_KEY!);
const result = await pinti.guardedAction(
{
amountMinor: 5000,
currency: "usd",
merchant: "AWS",
agentId: "agent-1",
category: "cloud",
reason: "EC2 instance",
},
async (auth) => {
const charge = await stripe.charges.create({
amount: 5000,
currency: "usd",
description: "EC2 instance via PINTI",
});
return {
railId: "stripe",
transactionId: charge.id,
actualAmountMinor: charge.amount,
actualCurrency: charge.currency,
};
}
);
// result.decision === "ALLOW"
// result.receipt.anomalyFlags === []
// result.receipt.receiptId === "cl..."MoonPay Example
const result = await pinti.guardedAction(
{
amountMinor: 10000, // $100.00
currency: "usd",
merchant: "moonpay:onramp",
agentId: "agent-1",
category: "crypto",
reason: "Buy ETH for gas fees",
},
async (auth) => {
const tx = await moonpay.createTransaction({
baseCurrencyAmount: 100,
baseCurrencyCode: "usd",
currencyCode: "eth",
});
return {
railId: "moonpay",
transactionId: tx.id,
actualAmountMinor: 10000,
actualCurrency: "usd",
actualNetwork: "moonpay",
};
}
);Custom Rail Example
const result = await pinti.guardedAction(
{
amountMinor: 2500,
currency: "usd",
merchant: "internal-credits",
agentId: "agent-1",
category: "credits",
reason: "Deduct credits for API usage",
},
async (auth) => {
const txId = await myCustomBilling.deductCredits({
userId: "user-123",
amount: 25.00,
});
return {
railId: "custom:internal-billing",
transactionId: txId,
actualAmountMinor: 2500,
actualCurrency: "usd",
};
}
);Error Handling
import { SpendDeniedError, ApprovalRequiredError } from "@pinti/guard";
try {
const auth = await pinti.authorize({
amountMinor: 50000, currency: "usd",
merchant: "expensive-service", agentId: "agent-1",
category: "saas", reason: "Enterprise plan",
});
} catch (err) {
if (err instanceof SpendDeniedError) {
console.log("Denied:", err.decisionReason);
// e.g. "EXCEEDS_DAILY_LIMIT", "BLOCKED_MERCHANT"
}
if (err instanceof ApprovalRequiredError) {
console.log("Needs approval:", err.spendRequestId);
// Wait for human to approve in PINTI dashboard
}
}| Error Class | When | Properties |
|---|---|---|
SpendDeniedError | Policy denies the spend | decisionReason, spendRequestId |
ApprovalRequiredError | Amount exceeds approval threshold | decisionReason, spendRequestId |
PintiApiError | HTTP error (401, 429, 500) | statusCode |
Anomaly Detection
When you submit a receipt, PINTI compares actual payment values against the SAT claims. Mismatches are flagged as anomalies:
| Flag | Meaning |
|---|---|
AMOUNT_MISMATCH | Actual amount differs from authorized amount |
CURRENCY_MISMATCH | Actual currency differs from authorized currency |
MERCHANT_MISMATCH | Actual merchant differs from authorized merchant |
STALE_POLICY | Policy was modified between authorization and receipt |
MISSING_RECEIPT | No receipt uploaded within expected window (SDK bypass) |
How SDK Guard Works
Note