Skip to content
Integrations
Integrations

Stripe

Trigger AgentField reasoners from signed Stripe webhooks.

Stripe connect dialog for a signed webhook trigger

The stripe source verifies the Stripe-Signature header and dispatches payment events through AgentField.

Source Surface

SurfaceValue
Source namestripe
KindHTTP webhook
SecretRequired; Stripe endpoint signing secret from secret_env
ConfigOptional tolerance_seconds, default 300
Event typeStripe event type
IdempotencyStripe event id
Reasoner inputNormalized { id, type, data } as event, with trigger metadata in _meta

Stripe does not ship a separate capability node in OSS. The integration surface is the signed webhook source.

Agent Code

from agentfield import Agent, on_event

app = Agent(node_id="billing-agent")

@app.reasoner()
@on_event(
    source="stripe",
    types=["payment_intent.succeeded", "checkout.session.completed", "invoice.paid"],
    secret_env="STRIPE_WEBHOOK_SECRET",
)
async def handle_stripe(event: dict, trigger=None):
    data = event.get("data", {}).get("object", {})
    return {
        "stripe_event": event.get("type"),
        "stripe_id": data.get("id"),
        "delivery": trigger.idempotency_key if trigger else event.get("id"),
    }

app.run()
import { Agent } from '@agentfield/sdk';

const agent = new Agent({ nodeId: 'billing-agent' });

// The stripe source verifies Stripe-Signature, then dispatches the
// normalized { id, type, data } as ctx.input.event with metadata in
// ctx.input._meta. The TypeScript SDK has no declarative source binding —
// connect the `stripe` source to this reasoner from the UI (or trigger REST API).
agent.reasoner('handleStripe', async (ctx) => {
  const { event, _meta } = ctx.input;
  const data = event?.data?.object ?? {};
  return {
    stripe_event: event?.type,
    stripe_id: data.id,
    delivery: _meta?.idempotency_key ?? event?.id,
  };
});

agent.serve();
a, _ := agent.New(agent.Config{NodeID: "billing-agent", Version: "1.0.0"})

// Declare the stripe binding in code. The control plane verifies
// Stripe-Signature with STRIPE_WEBHOOK_SECRET, then dispatches the
// normalized { id, type, data } as input["event"] with metadata in
// input["_meta"].
a.RegisterReasoner("handle_stripe", func(ctx context.Context, input map[string]any) (any, error) {
    event, _ := input["event"].(map[string]any)
    meta, _ := input["_meta"].(map[string]any)

    data := map[string]any{}
    if d, ok := event["data"].(map[string]any); ok {
        if obj, ok := d["object"].(map[string]any); ok {
            data = obj
        }
    }

    var delivery any = event["id"]
    if meta != nil {
        delivery = meta["idempotency_key"]
    }

    return map[string]any{
        "stripe_event": event["type"],
        "stripe_id":    data["id"],
        "delivery":     delivery,
    }, nil
},
    agent.WithEventTrigger("stripe", "payment_intent.succeeded", "checkout.session.completed", "invoice.paid"),
    agent.WithTriggerSecretEnv("STRIPE_WEBHOOK_SECRET"),
)

a.Serve(context.Background())

Stripe Setup

Create a webhook endpoint in Stripe and paste the AgentField trigger URL. Select the event types your reasoner handles and store the endpoint signing secret in the env var named by secret_env.

Common event types:

  • payment_intent.succeeded
  • checkout.session.completed
  • invoice.paid
  • customer.subscription.updated

Dispatch Contract

AgentField keeps the reasoner input small and stable:

{
  "event": {
    "id": "evt_123",
    "type": "invoice.paid",
    "data": {
      "object": { "id": "in_123", "customer": "cus_123" }
    }
  },
  "_meta": {
    "source": "stripe",
    "event_type": "invoice.paid",
    "idempotency_key": "evt_123"
  }
}
  • The Stripe event id becomes the idempotency key.
  • Signature timestamps are checked against a tolerance window.
  • The raw payload is stored for audit; the normalized event is dispatched to the reasoner.