---
title: "Quickstart: protect a Stripe refund with the SDK · Audon"
description: "Protect your first AI agent action with integrity.execute() from @audon/sdk in TypeScript: install, an agent key, a test refund, denials and retries."
url: https://audon.ai/docs/action-control/quickstart
last_updated: 2026-11-02
---
Action Control

# Quickstart: SDK

Protect your first action with integrity.execute() from @audon/sdk, in TypeScript.

Protect one refund end to end: create an agent and its key, send a test action, then connect Stripe and call `integrity.execute()` from your agent’s code. The first two steps take a minute and need no Stripe account. To give the agent MCP tools instead, see the [Action Gateway](https://audon.ai/docs/action-control/gateway).

## 1. Create an agent and an agent key

In the app, open **Agents** and fill in **Register an agent**: a name (the slug is made from it, for example `customer-support-agent`), the environment and the actions it may run (`refund.create`). On the agent’s **Keys** tab, click **Create agent key**. The secret (`aa_agent_…`) is shown once, together with ready snippets for curl, TypeScript, Claude Code, Cursor, the OpenAI Agents SDK, the Anthropic API and LangChain, with the key filled in.

An agent key is not an API key from **Developers**: those are for the Audon control plane and the Action Gateway rejects them.

## 2. Send a test action (no Stripe needed)

Every organization has a **Test connector**. It accepts test ids, simulates the provider and never moves money; test actions are marked Test everywhere and never billed or counted. Run the snippet for your client, or click **Send a test action** on the agent’s page: the page shows the first action as soon as it arrives.

```
curl -X POST https://audon.ai/v1/integrity/actions \
  -H "Authorization: Bearer $AUDON_AGENT_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: first-test-$(date +%s)" \
  -d '{"action_type":"refund.create","resource":"ch_test_refundable","amount_minor":100,"currency":"USD"}'
```

Test ids: `ch_test_refundable` (a USD 250.00 payment), `ch_test_refunded` (already refunded: blocked), `ch_test_disputed` (disputed: blocked), `cus_test_customer`, `sub_test_active`, `order_test_1001`.

## 3. Connect Stripe and turn on protection

Under Integrations → Action connectors, click **Connect with Stripe**: one install of the Audon app (a Shopify store works the same way with **Connect Shopify store**). Audon only reads until you click **Turn on protection** on the connector; there is no second install. Or use a **restricted key** (`rk_…`) with only the write permissions the action needs (for refunds: read on Charges and Refunds, write on Refunds). Turning on protection needs a signed-in person. See [connectors](https://audon.ai/docs/action-control/connectors).

Remove the agent’s direct access

From now on the agent reaches Stripe through Audon only. Remove any Stripe secret key from its environment, or the controls can be bypassed.

## 4. Install the SDK

Not on npm yet

`@audon/sdk` isn’t published to npm yet, so `npm install` won’t find it. Until it is, call the REST API (shown below), which is all the SDK does: everything on this page applies the same way. Ask us for the package if you want the typed client now.

bashInstall (once published)

```
npm install @audon/sdk
```

## 5. Execute an action

tsrefund.ts

```
import { Audon, idempotencyKey } from '@audon/sdk';

const audon = new Audon({ apiKey: process.env.AUDON_AGENT_KEY!, baseUrl: 'https://audon.ai' });

const result = await audon.integrity.execute({
  agent: 'customer-support-agent',     // optional: must match the key's agent
  action: 'refund.create',
  resource: 'ch_3QmX…',               // Stripe charge or payment intent
  amount: 45000,                       // minor units: USD 450.00
  currency: 'USD',
  idempotencyKey: idempotencyKey('refund', 'order_8812', 'ticket_5602'),
  reason: 'Customer reports the order never arrived',
});

switch (result.decision) {
  case 'allowed':          /* result.outcome: completed | failed | unknown | executing */ break;
  case 'denied':           /* tell the customer result.decision_reason; don't try another way */ break;
  case 'pending_approval': /* a person must approve: await audon.integrity.waitForOutcome(result.id) */ break;
  case 'would_deny':       /* monitoring: your policy would block it once you enforce; it ran */ break;
}
```

The same call over HTTP. The API’s field names are `action_type`, `amount_minor` and `idempotency_key` (or the `Idempotency-Key` header); it also accepts the SDK’s `action`, `amount` and `idempotencyKey`.

bashPOST /v1/integrity/actions

```
curl -X POST https://audon.ai/v1/integrity/actions \
  -H "Authorization: Bearer $AUDON_AGENT_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: refund-order_8812-ticket_5602" \
  -d '{ "action_type": "refund.create", "resource": "ch_3QmX…", "amount_minor": 45000, "currency": "USD" }'
```

## Rules of the road

- **One idempotency key per intent.** Reuse it on every retry of the same intent; a retry with the same key returns the original result (`replayed: true`) and never executes twice.
- **Decision and outcome are separate.** `decision` says whether Audon allowed it; `outcome` says what actually happened at the provider.
- **Unknown is not failure.** Don’t retry with a new key. Poll `status(id)` or `waitForOutcome(id)`; call `retry(id)` only when `retry_safe` is `true`.
- **Amounts are integers in minor units** of the currency (cents for USD, yen for JPY).
- **Retries in the client**: network errors and HTTP 408, 429, 502, 503 and 504 are retried (honouring `Retry-After`) up to `maxRetries` (default 2), always with the same key.

## Methods

| Method | What it does |
| --- | --- |
| `integrity.execute(input)` | `POST /v1/integrity/actions` with `Idempotency-Key` |
| `integrity.status(actionId)` | `GET /v1/integrity/actions/{id}/status` (this agent’s actions only) |
| `integrity.retry(actionId)` | `POST /v1/integrity/actions/{id}/retry`, only when `retry_safe` |
| `integrity.waitForOutcome(id, opts)` | Polls until completed, failed or not executed |
| `idempotencyKey(...parts)` | A deterministic key from the parts of one intent |

Errors are thrown as `AudonError` with `code` (`unauthenticated`, `insufficient_scope`, `validation_failed`, `idempotency_conflict`, `entitlement_required`, `rate_limited`, `network_error`, …), `status`, `details` and `requestId`. A denial is a result, not an error.

## Next

Write your first rule in [policies](https://audon.ai/docs/action-control/policies), and switch from monitoring to enforcing once the Would deny results look right ([modes](https://audon.ai/docs/action-control#modes)).

Last updated 2 November 2026
