- ›
Event booking agents need to pay real deposits— venue holds, ticket platforms, catering vendors — and a prompt alone cannot enforce a budget - ›Naïve gives each tenant user a governed virtual card with spending_limit_cents enforced by the card network, not the model
- ›Issue one card per event (or per vendor) scoped with naive.forUser(clientId) so one customer's agent never spends another's balance
- ›
Card creation and top-ups can freeze as pending_approval until a human approves— the risky moment stays gated even when the agent runs autonomously - ›Every charge lands in the tenant audit log, so finance can reconcile venue deposits against the event budget without trusting agent summaries
- ›
This pattern composes with the same Account Kit + forUser model as corporate travel— cards for events, cards for trips, one governance layer
An event coordinator agent that can email vendors and draft run-of-show documents still stops cold at the deposit link. Venues want a card hold. Ticket platforms want checkout. Catering wants 50% upfront. Naïve is the autonomous company infrastructure that gives agents real-world capabilities — and /cards is the primitive that turns "book this venue" into a governed payment the agent can complete without an open-ended corporate card in the prompt. This use case sits in the autonomous company spoke cluster — Company → Employee → Primitive in practice.
This guide shows how to give an event-booking agent a per-event virtual card: funded, capped, approval-gated where you need it, and scoped to one tenant user so multi-tenant event platforms stay isolated. The enforcement lives in the card network and the Naïve governance gateway — not in a system prompt the model can talk around.
This tutorial connects to the Multi-Tenant Playbook, spend caps and approvals, the sibling corporate travel desk pattern, and subscription spend cards — same /cards primitive, different use case.
Why event bookings need a card primitive
Event workflows split into two phases that agents handle differently:
| Phase | Agent-friendly? | Needs money? |
|---|---|---|
| Research & coordination | Yes — search, email, calendar | No |
| Confirm & pay | Risky without enforcement | Yes — deposits, tickets, vendor invoices |
Most teams solve the payment phase by giving the agent a shared corporate card number or pasting credentials into a vault the model can read. Both fail the same test: there is no hard ceiling the agent cannot exceed, and there is no per-customer isolation when you run multi-tenant.
The Company → Employee → Primitive model applies here: your platform (Company) defines policy, each customer's event agent (Employee) acts on their behalf, and /cards is the Primitive that binds spend to that agent with a limit you set in cents.
Architecture
Four pieces work together:
- Users — one tenant user per customer or event planner.
- Account Kits — enable cards, set default limits, gate issuance.
- Cards — virtual card per event, funded through checkout.
- Approvals — human gate on sensitive spend actions.
Setup
npm install @usenaive-sdk/serverimport { Naive, isPendingApproval } from "@usenaive-sdk/server";
const naive = new Naive({ apiKey: process.env.NAIVE_API_KEY! });Use naive.forUser(customerId) for every call that touches cards — that scopes identity, spend, and audit to one tenant.
Step 1 — Encode event spend policy in an Account Kit
const eventKit = await naive.accountKits.create({
name: "Event booking — standard",
primitives_config: {
cards: {
enabled: true,
requiresApproval: true,
defaults: { spending_limit_cents: 250_000 }, // $2,500 default per card
},
formation: { enabled: false },
verification: { enabled: false },
},
});requiresApproval: true on cards means creating or topping up a card freezes until a human approves — the right default when venue deposits can be four figures.
Step 2 — Create a tenant user per customer
const planner = await naive.users.create({
external_id: "acme-events-001",
email: "events@acme.com",
account_kit_id: eventKit.id,
});
const client = naive.forUser(planner.id);Every card, transaction log, and approval queue entry below is scoped to planner.id. Another customer's event agent cannot see this balance.
Step 3 — Issue a per-event card
When the agent confirms "Annual Summit — venue deposit $1,800," issue a card scoped to that event:
const card = await client.cards.create({
name: "Annual Summit — venue deposit",
spending_limit_cents: 180_000,
});
if (isPendingApproval(card)) {
// Surface card.approval_id in your UI; manager approves, then replay.
return { status: "pending_approval", approvalId: card.approval_id };
}
// Fund via checkout_url, then check-payment to activate (per docs)The spending_limit_cents value is the hard cap — the card network declines anything above it. The agent cannot negotiate a higher limit through prompting.
For smaller line items (ticket platform fees, swag vendors), a prepaid gift card under the documented maximum may be enough — no cardholder required. For recurring event clients, a managed virtual card supports higher limits after cardholder setup. Details in the cards docs.
Step 4 — Let the agent complete checkout, log the charge
Once the card is active, the agent retrieves credentials through the governed API (never echoed to the model in plain text in your app — use secure reveal flows per docs) and completes the venue or ticket checkout.
After payment:
// Manual logging uses the card log-transaction endpoint:
await fetch(`https://api.usenaive.ai/v1/cards/${card.id}/log-transaction`, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.NAIVE_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
amount_cents: 180_000,
merchant_name: "Grand Hall Events",
description: "Venue deposit — Annual Summit 2026",
}),
});Managed virtual cards may also capture transactions via webhooks; manual logging covers prepaid flows and offline reconciliation.
Step 5 — Revoke or let the card expire after the event
When the event closes, unassign the agent and freeze further spend — or revoke the tenant user's session entirely if the engagement ended. Card revocation is absolute on Naïve: no further authorizations clear. See instant revocation for the broader pattern.
What this enables for event operators
- Venue deposits — one card, one limit, one approval gate.
- Ticket platforms — capped checkout without sharing a company Amex in a prompt.
- Catering & AV vendors — separate cards per vendor category if your kit allows multiple active cards.
- Multi-tenant SaaS — each client's events agent spends only their funded balance.
The agent still does the coordination work (email, search, scheduling). /cards is what makes the payment step real and bounded.
Related reading
- Introducing /cards — primitive overview
- Corporate travel desk — same cards pattern for trips
- Spend caps, approvals, and revocation — governance deep dive
- Cards documentation — API reference
Can an AI agent actually pay for event bookings?+
How do you stop an event agent from overspending on a deposit?+
How does multi-tenant event booking work?+
What is the difference between event booking cards and a corporate travel card?+
Which card type should an event agent use?+
Building the autonomous company infrastructure.
Issue virtual cards for your agents — a prepaid gift card or a managed virtual card — funded via checkout, capped by a spending limit, and fully audited.
Build a multi-tenant corporate travel desk with the Naïve SDK: an AI agent that researches, ranks, and books hotels, with spend capped and approvals enforced.
Issue per-tool virtual cards for AI agents buying SaaS subscriptions — monthly caps on the card network, approval gates, and instant revocation on churn.
Spend caps, human approvals, and instant revoke for AI agents must be enforced server-side — Naïve's governance gateway applies all three on every call.