diff --git a/api-reference/webhooks.mdx b/api-reference/webhooks.mdx index 3d6adb7..87e648b 100644 --- a/api-reference/webhooks.mdx +++ b/api-reference/webhooks.mdx @@ -40,7 +40,7 @@ If none of the three is set, nothing is sent. That's not an error, it's silent b "payer": null, "payer_type": "human", "network": "stripe", - "testnet": false, + "livemode": true, "overpaid_by_cents": null, "metadata": { "orderId": "order-123" } } @@ -57,7 +57,7 @@ If none of the three is set, nothing is sent. That's not an error, it's silent b On-chain payer address. `null` for card/bank rails. `human` or `agent`. CAIP-2 network ID for on-chain rails, or `stripe` for card/bank. -`true` on a test-mode checkout. +`true` in live mode, `false` in test mode. Set when a bank-transfer buyer sent more than the amount due (beyond a 1-cent tolerance). `null` otherwise. Whatever you set on the checkout (or its link), unchanged. @@ -76,7 +76,7 @@ If none of the three is set, nothing is sent. That's not an error, it's silent b "token": "USDC", "chain_id": 8453, "network": "eip155:8453", - "testnet": false, + "livemode": true, "description": null } } @@ -99,14 +99,14 @@ Identical shape to `send.completed`, with `tx_hash: null`. "token": "USDC", "chain_id": 8453, "network": "eip155:8453", - "testnet": false, + "livemode": true, "description": null } } ``` -The raw payload above is the literal snake_case JSON body AgentaOS `POST`s to your `webhookUrl`, this is what you'll parse in any language other than the SDK. `agentaos.webhooks.verify()` (Node.js) parses it and returns a camelCased, typed object instead: `linkId`, `sessionId`, `txHash`, `payerType`, etc. `rail`, `vendor_reference`, `testnet`, and `overpaid_by_cents` are additive fields not yet reflected in the SDK's TypeScript types, they arrive on the wire regardless of language. +The raw payload above is the literal snake_case JSON body AgentaOS `POST`s to your `webhookUrl`, this is what you'll parse in any language other than the SDK. `agentaos.webhooks.verify()` (Node.js) parses it and returns a camelCased, typed object instead: `linkId`, `sessionId`, `txHash`, `payerType`, `livemode`, etc. `rail`, `vendor_reference`, and `overpaid_by_cents` arrive on the wire but are not yet reflected in the SDK's TypeScript types, they're present regardless of language. ## Delivery diff --git a/sdk/pay-webhooks.mdx b/sdk/pay-webhooks.mdx index 1ee4fed..191f0c5 100644 --- a/sdk/pay-webhooks.mdx +++ b/sdk/pay-webhooks.mdx @@ -82,7 +82,7 @@ A discriminated union on `type`. `switch`/narrow on it to get typed `data`. Unique event ID, `evt_`. Present on every event, both on the wire and on the object `verify()` returns. - + Inside every event's `data`, **`amount` is a string**, e.g. `"49.99"`, not the `number` you get back from `checkouts.create()` or `paymentLinks.create()`. Parse it before doing math. See the [money model](/sdk/pay-overview#the-money-model). @@ -100,6 +100,7 @@ Fires when a checkout session's payment confirms. Payer wallet address. CAIP-2 network ID. +`true` in live mode, `false` in test mode. Whatever `metadata` you passed at `checkouts.create()`. ### `send.completed` @@ -114,6 +115,7 @@ Fires when an outbound send (a payout or transfer you initiated) is broadcast su +`true` in live mode, `false` in test mode. ### `send.failed` @@ -128,8 +130,24 @@ Same shape as `send.completed`, but `txHash` is always `null` and no broadcast s +`true` in live mode, `false` in test mode. +### `subscription.*` + +All five `subscription.*` events carry the same `SubscriptionData`, delivered to your organization webhook endpoint. + +The subscription ID. +Stripe status, verbatim: `incomplete`, `active`, `trialing`, `past_due`, `unpaid`, or `canceled`. +The plan name, from the backing payment link. + +Per-cycle price in integer minor units. `1000` means `€10.00`. +ISO 8601 timestamp, or `null` before the first cycle is set. +`true` once a cancellation is scheduled for period end. + + +`true` in live mode, `false` in test mode. + `successUrl` is best-effort, the customer might close their browser before the redirect lands. Fulfill orders from the webhook (server-to-server, reliable), not the redirect. diff --git a/webhooks/events.mdx b/webhooks/events.mdx index 4956c28..6027ca3 100644 --- a/webhooks/events.mdx +++ b/webhooks/events.mdx @@ -3,7 +3,7 @@ title: "Events" description: "Every webhook event AgentaOS sends: full payload fields, types, and a JSON example for each." --- -AgentaOS sends three event types today. Every event shares the same envelope, an `id`, a `type`, and a `data` object whose shape depends on the type. See [Webhooks](/payments/webhooks) for how to register a URL and verify the signature before trusting any of this. +AgentaOS sends webhook events for checkouts, outbound sends, and subscriptions. Every event shares the same envelope, an `id`, a `type`, and a `data` object whose shape depends on the type. See [Webhooks](/payments/webhooks) for how to register a URL and verify the signature before trusting any of this. Every `amount` field below is a **string** (e.g. `"49.99"`), not a number. This differs from `amount` on SDK create calls (checkouts, payment links), which is a plain number in currency units. Parse it before doing arithmetic. @@ -18,7 +18,7 @@ The field names below are the literal snake_case keys AgentaOS `POST`s to your ` - One of `checkout.session.completed`, `send.completed`, `send.failed`. Switch on this to decide how to parse `data`. + One of `checkout.session.completed`, `send.completed`, `send.failed`, or a `subscription.*` event. Switch on this to decide how to parse `data`. @@ -62,8 +62,8 @@ Fired when a checkout is paid, by card, wallet, or stablecoin. This is the event CAIP-2 network ID for on-chain rails, e.g. `"eip155:8453"` for Base, or `stripe` for card/bank. - - `true` on a test-mode checkout, `false` in live. + + `true` in live mode, `false` in test mode. Set when a bank-transfer buyer sent more than the amount due (beyond a 1-cent tolerance). `null` otherwise. @@ -92,7 +92,7 @@ Fired when a checkout is paid, by card, wallet, or stablecoin. This is the event "payer": null, "payer_type": "human", "network": "stripe", - "testnet": false, + "livemode": true, "overpaid_by_cents": null, "metadata": { "orderId": "order-123" } } @@ -128,8 +128,8 @@ Fired when an outbound stablecoin send you initiated confirms on-chain. CAIP-2 network ID, e.g. `"eip155:8453"`. - - `true` on a test-mode send, `false` in live. + + `true` in live mode, `false` in test mode. Optional description you attached to the send. `null` if none was set. @@ -149,7 +149,7 @@ Fired when an outbound stablecoin send you initiated confirms on-chain. "token": "USDC", "chain_id": 8453, "network": "eip155:8453", - "testnet": false, + "livemode": true, "description": "Payout to contractor" } } @@ -184,8 +184,8 @@ Fired when an outbound send fails to broadcast, network error, insufficient bala CAIP-2 network ID, e.g. `"eip155:8453"`. - - `true` on a test-mode send, `false` in live. + + `true` in live mode, `false` in test mode. Optional description you attached to the send. `null` if none was set. @@ -205,7 +205,7 @@ Fired when an outbound send fails to broadcast, network error, insufficient bala "token": "USDC", "chain_id": 8453, "network": "eip155:8453", - "testnet": false, + "livemode": true, "description": null } } @@ -215,6 +215,48 @@ Fired when an outbound send fails to broadcast, network error, insufficient bala `send.failed` means the transaction never landed on-chain. It's distinct from a payment dispute or a card decline, those don't go through this event, they affect your balance directly. See [Payouts](/payouts/overview). +## Subscription events + +Subscription lifecycle events, delivered to your **organization** webhook endpoint. All five share the same `data` shape. + +- **`subscription.created`** first payment succeeded; now active (or trialing). +- **`subscription.renewed`** a cycle was paid and renewed for another period. +- **`subscription.payment_failed`** a renewal payment failed; now past due. +- **`subscription.updated`** the subscription changed (commonly `cancel_at_period_end`). +- **`subscription.canceled`** terminal; no further charges. + + + The subscription ID. + Stripe status: `active`, `trialing`, `past_due`, `unpaid`, `canceled`, `incomplete`. + Plan name, from the backing payment link. + e.g. `"EUR"`. + Per-cycle price in integer minor units. `1000` = `€10.00`. + ISO 8601, or `null` before the first cycle. + `true` if cancellation is scheduled for period end. + + + `true` in live mode, `false` in test mode. + + +```json Example +{ + "id": "evt_3f2a1b0c-9d8e-7f6a-5b4c-3d2e1f0a9b8c", + "type": "subscription.renewed", + "data": { + "id": "sub_6pC2lNB6joCRQIZ1aMrTpi", + "status": "active", + "plan_name": "Pro Monthly", + "currency": "EUR", + "amount_minor": 1000, + "current_period_end": "2026-09-19T12:00:00.000Z", + "cancel_at_period_end": false, + "customer_email": "customer@example.com", + "customer_name": "Alex Rivera", + "livemode": true + } +} +``` + ## Next steps