Getting Started

Getting Started with ArmorPay

Enable ArmorPay, apply a bundle template from the dashboard, and wire an AP, Finance, or Payroll agent into enforcement through the ArmorIQ SDK.

There are two independent pieces to adopting ArmorPay: turning on the policy side (a bundle template applied to your agent) and turning on the enforcement side (the agent's code actually calling through ArmorIQ before it moves money). Most teams do both, but you can apply a bundle to an agent that isn't wired up yet - it just won't be enforced until the agent calls the SDK.

Prerequisites

  • A verified ArmorIQ account and organization membership.
  • An ArmorIQ API key - see API Keys.
  • ArmorPay enabled for your org (see below).
  • Your payments, AP, finance, or payroll agent registered as a target in ArmorIQ (targetType: agent or mcp_server).

Step 1: Enable ArmorPay

ArmorPay is an optional product toggle:

  1. Go to Settings → Product Preferences.
  2. Toggle ArmorPay on for your org.
  3. The ArmorPay section (Dashboard and Policy Studio) appears in your sidebar.

Step 2: Apply a bundle template

The fastest path to a working policy is the ArmorPay Dashboard: pick your agent, pick one of its three bundle templates (standard, restricted, or permissive posture), and click Apply. This imports a ready-made Policy document scoped to that agent - see Bundle Templates for the full catalog and Concepts for what's actually inside the YAML.

Use Customize instead of Apply to open the same bundle in the Policy Studio and adjust thresholds, roles, or transaction types before deploying.

Step 3: Wire the agent through the SDK

ArmorPay agents (payments, AP, finance, payroll) run in SDK mode: they don't sit behind the MCP proxy. Instead, the agent's own process calls the ArmorIQ backend directly with @armoriq/sdk (TypeScript) or armoriq-sdk (Python), using the same plan → token → invoke flow every SDK integration uses:

import { ArmorIQClient } from '@armoriq/sdk';

const client = new ArmorIQClient({
  apiKey: process.env.ARMORIQ_API_KEY!,
  userId: 'ap-service',
  agentId: 'ap-agent',
});

const plan = client.capturePlan(
  'gpt-4o',
  'Create an invoice for Acme Corp for $8,400',
  {
    goal: 'Create invoice',
    steps: [{ action: 'create_invoice', mcp: 'ap-mcp', params: { customer: 'Acme Corp', amount: 8400 } }],
  },
);

const token = await client.getIntentToken(plan);

const result = await client.invokeWithPolicy(
  'ap-mcp',
  'create_invoice',
  token,
  { customer: 'Acme Corp', amount: 8400 },
  { userEmail: 'ap-clerk@customer.com', waitForApproval: true },
);

invokeWithPolicy is the richer call: it's the one that understands hold outcomes and can poll for an approval automatically (waitForApproval). Plain invoke also works, but you'll need to handle PolicyHoldException yourself. See the TypeScript SDK and Python SDK references for the full API, and Frameworks if your agent isn't a bare client (for example Google ADK).

Nothing in this call is ArmorPay-specific. The AP/Finance/Payroll bundle templates just populate the amountThreshold, velocityLimit, recipientValidation, and transactionTypeControl fields inside a normal ArmorIQ policy - see Concepts for the shape.

Step 4: Handle blocks and holds

invokeWithPolicy raises PolicyBlockedException when the policy's enforcementAction is block, and PolicyHoldException when it's hold (for example, an invoice above the bundle's approval threshold):

import { PolicyBlockedException, PolicyHoldException } from '@armoriq/sdk';

try {
  await client.invokeWithPolicy('ap-mcp', 'create_invoice', token, params, {
    userEmail: 'ap-clerk@customer.com',
    waitForApproval: true,
    holdPollIntervalMs: 3000,
    holdPollAttempts: 20,
  });
} catch (err) {
  if (err instanceof PolicyBlockedException) {
    // Amount, vendor, or transaction type is outside the policy - do not retry silently.
  } else if (err instanceof PolicyHoldException) {
    // Needs a human approver. If waitForApproval was set, this only throws
    // after the poll window expires without a decision.
  }
}

A held call opens a delegation request that an approver resolves from the plan view. For direct-client integrations (AP, Finance, Payroll agents calling the SDK without a framework wrapper), the delegation window is short - approvals generally need to land within a few minutes, so build your UI or on-call process around a fast approve/reject path rather than a multi-hour queue.

Next steps

On this page