Skip to main content
This guide walks through the complete flow for integrating AgentCard into your product — from initial setup to issuing and managing cards programmatically on behalf of your users.
This page is designed to be self-contained. You can hand it to an AI agent or developer and they’ll have everything needed to implement the full integration.

Overview

CLI setup (one-time)          API operations (repeatable)
─────────────────────         ─────────────────────────────
1. Login                      3. Create cardholders
2. Create org + API key  -->  4. Attach payment methods
                              5. Issue cards
                              6. Get card credentials
                              7. Close cards
Steps 1–2 use the agent-cards-admin CLI. Steps 3–7 use the REST API with your API key.

Phase 1: Setup (CLI, one-time)

Install and log in

npm install -g agent-cards-admin
agent-cards-admin login
# Enter your email -> click the magic link -> authenticated

Create an organization

Organizations are the billing unit. All cardholders, cards, and API keys are scoped to an org.
agent-cards-admin orgs create --name "My Company" --email billing@mycompany.com
Save the org ID from the output (e.g. org_abc123).

Create an API key

agent-cards-admin keys create --org <org-id> --name "production-key"
Save the API key — it starts with sk_test_ (sandbox) or sk_live_ (production) and won’t be shown again.
export AGENTCARD_API_KEY="sk_test_..."
Use sk_test_ keys during development. Sandbox mode uses Stripe’s test environment — no real charges are made. Switch to sk_live_ keys for production.

Other CLI commands

agent-cards-admin orgs list                                            # list orgs
agent-cards-admin orgs get <org-id>                                    # org details
agent-cards-admin keys list --org <org-id>                             # list API keys
agent-cards-admin keys revoke                                          # revoke a key
agent-cards-admin keys rotate                                          # rotate a key
agent-cards-admin members add --org <org-id> --email teammate@co.com   # add team member
agent-cards-admin members list --org <org-id>                          # list members

Phase 2: API Integration

All endpoints below use API key authentication:
Authorization: Bearer sk_test_...
Content-Type: application/json
Base URL: https://api.agentcard.sh (production) or https://sandbox.api.agentcard.sh (sandbox)

Step 1: Create a cardholder

Each user who will have cards issued on their behalf needs a cardholder record.
curl -X POST https://api.agentcard.sh/api/v1/cardholders \
  -H "Authorization: Bearer $AGENTCARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "firstName": "Jane",
    "lastName": "Smith",
    "dateOfBirth": "1990-03-15",
    "phoneNumber": "+14155551234",
    "email": "jane@example.com"
  }'
FieldTypeRequiredNotes
firstNamestringYesNon-empty
lastNamestringYesNon-empty
dateOfBirthstringYesISO date, e.g. "1990-03-15"
phoneNumberstringYesNon-empty
emailstringNoMust be unique within the organization
Response
{
  "id": "ch_abc123",
  "firstName": "Jane",
  "lastName": "Smith",
  "email": "jane@example.com",
  "dateOfBirth": "1990-03-15T00:00:00.000Z",
  "phoneNumber": "+14155551234",
  "stripeCardholderId": "ich_1abc123",
  "createdAt": "2026-03-10T12:00:00.000Z",
  "updatedAt": "2026-03-10T12:00:00.000Z"
}
ErrorCause
400Missing or invalid required field
409A cardholder with this email already exists in the org
See also: List cardholders, Get cardholder, Update cardholder

Step 2: Attach a payment method

Each cardholder needs a payment method before you can issue cards. This creates a Stripe Checkout session the user must complete in a browser.
curl -X POST https://api.agentcard.sh/api/v1/cardholders/ch_abc123/payment-method/setup \
  -H "Authorization: Bearer $AGENTCARD_API_KEY"
No request body needed.
Response
{
  "checkoutUrl": "https://checkout.stripe.com/c/pay/cs_test_abc123...",
  "stripeSessionId": "cs_test_abc123"
}
Redirect the user to checkoutUrl to complete payment method setup. After the user completes it, the payment method is automatically saved.

Step 3: Verify payment method

Poll this endpoint to confirm the user completed payment method setup before issuing cards.
curl https://api.agentcard.sh/api/v1/cardholders/ch_abc123/payment-method/status \
  -H "Authorization: Bearer $AGENTCARD_API_KEY"
Response (ready)
{
  "hasPaymentMethod": true,
  "paymentMethodId": "pm_abc123"
}
Response (not yet)
{
  "hasPaymentMethod": false
}

Step 4: Create a card

Issue a single-use virtual Visa card. The amountCents is authorized (held) on the cardholder’s payment method immediately.
curl -X POST https://api.agentcard.sh/api/v1/cards \
  -H "Authorization: Bearer $AGENTCARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"amountCents": 2500, "cardholderId": "ch_abc123"}'
FieldTypeRequiredNotes
amountCentsintegerYesPositive integer. Max 50.00(5000)onfreeplan,50.00 (5000) on free plan, 500.00 (50000) on basic plan.
cardholderIdstringYesID from Step 1
Response
{
  "id": "card_abc123",
  "cardholderId": "ch_abc123",
  "last4": "4242",
  "expiry": "12/27",
  "spendLimitCents": 2500,
  "balanceCents": 2500,
  "status": "OPEN",
  "createdAt": "2026-03-10T12:00:00.000Z"
}
ErrorCause
400amountCents invalid or exceeds maximum
402Payment method declined. The declined method is automatically detached.
404Cardholder not found
422No payment method. Response includes setupUrl to initiate setup.
{
  "status": "payment_method_required",
  "message": "Cardholder has no payment method. Set one up first.",
  "setupUrl": "/api/v1/cardholders/ch_abc123/payment-method/setup"
}

Step 5: Get card credentials

Retrieve the full card number (PAN), CVV, and expiry for your agent to use.
curl https://api.agentcard.sh/api/v1/cards/card_abc123/details \
  -H "Authorization: Bearer $AGENTCARD_API_KEY"
Response
{
  "id": "card_abc123",
  "cardholderId": "ch_abc123",
  "pan": "4242424242424242",
  "cvv": "123",
  "expiry": "12/27",
  "last4": "4242",
  "balanceCents": 2500,
  "spendLimitCents": 2500,
  "status": "OPEN"
}
All card credential access is logged in the audit trail.

Step 6: Close a card

Permanently close a card and release any held funds. Idempotent — closing an already-closed card returns success.
curl -X DELETE https://api.agentcard.sh/api/v1/cards/card_abc123 \
  -H "Authorization: Bearer $AGENTCARD_API_KEY"
Response
{
  "id": "card_abc123",
  "status": "CLOSED"
}

List and filter cards

curl "https://api.agentcard.sh/api/v1/cards?status=OPEN&cardholderId=ch_abc123&limit=10" \
  -H "Authorization: Bearer $AGENTCARD_API_KEY"
ParameterTypeDefaultNotes
limitinteger501–100
offsetinteger0
statusstringOPEN, IN_USE, CLOSED, PAUSED
cardholderIdstringFilter by cardholder
Response
{
  "cards": [ { "id": "...", "last4": "4242", "status": "OPEN", ... } ],
  "total": 1,
  "limit": 10,
  "offset": 0
}

Card lifecycle

OPEN  ──>  IN_USE  ──>  CLOSED
  |                        ^
  +────────────────────────+
          (close)
  • OPEN — Card is issued and ready to use. Funds are held on the cardholder’s payment method.
  • IN_USE — A transaction has been authorized on the card.
  • CLOSED — Card is permanently closed (via API, auto-close after single use, or spend limit reached).
Cards are single-use by default. After one successful transaction, the card auto-cancels.

Error responses

All errors return JSON:
{
  "error": "error_code_or_message"
}
StatusMeaning
400Bad request — missing or invalid fields
401Unauthorized — invalid or missing API key
402Payment failed — card declined or authorization failed
403Forbidden — org suspended or beta capacity reached
404Resource not found
409Conflict — duplicate resource (e.g. cardholder email)
422Precondition not met (e.g. no payment method)
429Rate limit exceeded (default: 1,000 req/hour per key)
500Internal server error
502Provider error — upstream card provider failed

Webhooks

Register a webhook endpoint to receive real-time notifications about card events.

Register an endpoint

curl -X POST https://api.agentcard.sh/user-webhooks \
  -H "Authorization: Bearer <jwt>" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://yourapp.com/webhooks/agentcard",
    "events": ["card.created", "charge.authorized", "card.cancelled", "balance.low"]
  }'
Use "*" to subscribe to all events. The response includes a secret (shown once) for signature verification.

Event types

EventDescription
card.createdA new card was issued
charge.authorizedA transaction was authorized on a card
card.cancelledA card was closed
balance.lowA card’s balance is running low

Webhook payload

{
  "event": "charge.authorized",
  "createdAt": "2026-03-10T12:05:00.000Z",
  "data": {
    "cardId": "card_abc123",
    "last4": "4242",
    "amountCents": 1500,
    "merchant": "ACME Corp"
  }
}

Signature verification

Each delivery includes an X-AgentCard-Signature header — an HMAC-SHA256 of the request body signed with your endpoint’s secret.
const crypto = require('crypto');

function verifyWebhook(body, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(body)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}
Failed deliveries are retried up to 3 times: immediately, after 1 minute, after 5 minutes.

Manage endpoints

# List
curl https://api.agentcard.sh/user-webhooks \
  -H "Authorization: Bearer <jwt>"

# Update
curl -X PATCH https://api.agentcard.sh/user-webhooks/<id> \
  -H "Authorization: Bearer <jwt>" \
  -H "Content-Type: application/json" \
  -d '{"status": "disabled"}'

# Delete
curl -X DELETE https://api.agentcard.sh/user-webhooks/<id> \
  -H "Authorization: Bearer <jwt>"

Complete example

# -- Setup (one-time, via CLI) --
npm install -g agent-cards-admin
agent-cards-admin login
agent-cards-admin orgs create --name "My Company" --email billing@mycompany.com
agent-cards-admin keys create --org <org-id> --name "my-key"
# Save the sk_test_... key

# -- API operations --
export AGENTCARD_API_KEY="sk_test_..."
export BASE="https://api.agentcard.sh"

# Create cardholder
CARDHOLDER=$(curl -s -X POST "$BASE/api/v1/cardholders" \
  -H "Authorization: Bearer $AGENTCARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"firstName":"Jane","lastName":"Smith","dateOfBirth":"1990-03-15","phoneNumber":"+14155551234","email":"jane@example.com"}')
CARDHOLDER_ID=$(echo $CARDHOLDER | jq -r '.id')

# Setup payment method -> send user to checkoutUrl
SETUP=$(curl -s -X POST "$BASE/api/v1/cardholders/$CARDHOLDER_ID/payment-method/setup" \
  -H "Authorization: Bearer $AGENTCARD_API_KEY")
echo "User must visit: $(echo $SETUP | jq -r '.checkoutUrl')"

# Verify payment method attached
curl -s "$BASE/api/v1/cardholders/$CARDHOLDER_ID/payment-method/status" \
  -H "Authorization: Bearer $AGENTCARD_API_KEY"

# Create a $25 card
CARD=$(curl -s -X POST "$BASE/api/v1/cards" \
  -H "Authorization: Bearer $AGENTCARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"amountCents\":2500,\"cardholderId\":\"$CARDHOLDER_ID\"}")
CARD_ID=$(echo $CARD | jq -r '.id')

# Get credentials
curl -s "$BASE/api/v1/cards/$CARD_ID/details" \
  -H "Authorization: Bearer $AGENTCARD_API_KEY"

# Close card
curl -s -X DELETE "$BASE/api/v1/cards/$CARD_ID" \
  -H "Authorization: Bearer $AGENTCARD_API_KEY"

Next steps

API Reference

Full reference for all REST API endpoints.

Sandbox

Test your integration with sandbox API keys.