Skip to main content
Webhooks let your server react to events in your AgentCard organization the moment they happen — without polling. When a card is created, a cardholder is updated, a transaction is authorized, or a card is closed, we POST a signed JSON payload to a URL you control.

When to use webhooks

Reach for webhooks when you need to:
  • Reconcile transactions in your own ledger as they clear.
  • Notify a user when their card was used.
  • Trigger downstream workflows on card lifecycle changes (e.g. mark a procurement as complete when a card closes).
  • Detect declines and react (e.g. notify a fraud queue).
If you only need on-demand state, the GET /api/v1/cards and GET /api/v1/cards/:id endpoints are simpler.

How it works

  1. You register an endpoint with the URL of your receiver and the list of events you care about.
  2. AgentCard returns a signing secret (whsec_…). Store it in your receiver’s environment; if you lose it, reveal it again or rotate it (every retrieval is audited).
  3. When an event occurs, we POST a JSON payload to your URL with two signature headers.
  4. Your server verifies the signature, processes the event, and returns 2xx quickly.
  5. On any non-2xx response (or network error) we retry with backoff up to 5 attempts over ~1 hour 36 minutes.

Quickstart

Register an endpoint with the CLI:
agent-cards-admin webhooks create \
  --url https://your-app.example.com/webhooks/agentcard \
  --events 'card.*,transaction.authorized,transaction.declined'
Or with the API directly:
curl -X POST https://api.agentcard.sh/api/v1/webhook_endpoints \
  -H "Authorization: Bearer sk_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.example.com/webhooks/agentcard",
    "enabled_events": ["card.*", "transaction.authorized"]
  }'
The response contains a secret field. Copy it into your server’s environment as AGENTCARD_WEBHOOK_SECRET. If you lose it later, run agent-cards-admin webhooks reveal <id> (or GET /api/v1/webhook_endpoints/:id/secret).

Payload shape

Every webhook body is an event envelope:
{
  "id": "evt_a1b2c3d4e5f6a7b8c9d0e1f2",
  "type": "card.created",
  "created": 1763356800,
  "livemode": true,
  "data": {
    "id": "cm3abc123",
    "cardholder_id": "ch_abc123",
    "last4": "4242",
    "expiry": "03/28",
    "spend_limit_cents": 1000,
    "balance_cents": 1000,
    "status": "OPEN",
    "created_at": "2026-05-17T12:00:00.000Z"
  }
}
FieldTypeNotes
idstringStable event ID. Use this to dedupe.
typestringEvent type. See Events.
createdintegerUnix epoch seconds.
livemodebooleanfalse for events from sk_test_* keys (test mode).
dataobjectEvent-specific payload. Shape depends on type.

Next steps

Event catalog

Every event type with example payloads.

Verify signatures

Node, Python, and Go verification snippets.

Testing webhooks

Local development with ngrok and the CLI.

Best practices

Idempotency, fast 2xx, retries, and rotation.