Skip to main content
AgentaOS sends 12 webhook event types, for checkouts, outbound sends, subscriptions, disputes, account verification, and the dashboard’s test event. This page is the full list. Every event shares the same envelope: an id, a type, a business, and a data object whose shape depends on the type. See Webhooks for how to register a URL and verify the signature before you trust any of this. Amounts follow the money model: amount is a string in currency units, and amount_minor is an integer in the smallest currency unit.
The field names below are the literal snake_case keys AgentaOS POSTs to your webhookUrl: parse these in any language. The SDK’s webhooks.verify() (Node.js) returns the same fields camelCased: link_id becomes linkId, session_id becomes sessionId, trial_end becomes trialEnd, and so on.

When each event fires

Each event type below lists every trigger in the platform. Which action fires which event gives the same facts in the other direction, per action.

Event envelope

string
The event ID. A paid checkout’s id is evt_ plus the sale’s transaction id, a send’s id is evt_ plus data.transaction_id, and every other event gets a random id such as evt_4e1b9a0c2d3f5a67. An event keeps its id across delivery attempts and a retry from the dashboard. The SDK’s WebhookEvent type does not declare id yet, so deduplicate on the keys in Deduplication.
string
One of checkout.session.completed, checkout.session.bank_transfer_pending, send.completed, send.failed, subscription.created, subscription.renewed, subscription.payment_failed, subscription.updated, subscription.canceled, dispute.created, dispute.closed, account.updated, or webhook.test. Switch on this to decide how to parse data.
string
The id of the business the event happened in. On your own events it is your own id. If you are a platform, your webhook also receives the events of every business you manage, and there business is your client’s id. See Platform webhooks.
object
Event-specific payload. See each event below.

Which action fires which event

Events describe money and account state, not every API call. An action that changes nothing about a payment, a subscription or a business’s verification sends no event. A “check” below is AgentaOS reading the current state from the card processor. While the buyer’s checkout page is open, AgentaOS checks within seconds. A background check runs every 5 minutes for subscriptions and every 10 minutes for disputes.

Your API calls

Actions outside your API calls

For the order of the subscription events, see Event order for subscriptions.

Which URL receives an event

A checkout.session.completed event goes to one URL: the checkout’s own webhookUrl if it has one, else its payment link’s, else your account’s webhook URL. The first one found is the only one that receives it. Every other event goes to your account’s webhook URL. If no URL applies, AgentaOS sends nothing and shows no error.

Delivery and retries

AgentaOS sends each event as a POST with Content-Type: application/json and an X-AgentaOS-Signature header. A delivery follows these rules:
  • Each attempt times out after 10 seconds. A response outside 2xx, a timeout, or a network error counts as a failed attempt.
  • AgentaOS makes up to 3 attempts. It waits 1 second before the second attempt and 2 seconds before the third.
  • The 3 attempts carry the same signature, with the same t.
  • AgentaOS does not follow redirects. A 3xx response is a failed attempt.
  • AgentaOS refuses a URL that resolves to a private or internal address, such as localhost, 10.0.0.0/8 or 192.168.0.0/16, and marks the event failed without an attempt. For local development, expose your server through a public HTTPS tunnel.
After the third failed attempt, AgentaOS marks the event failed in Settings → Developers → Webhooks and sends it no more by itself. An owner or admin can send a failed event again with the retry button on its row (labeled “Retry webhook”). The retry sends the same body, signed again with a new t. Events are delivered independently of each other. Two events about the same subscription can arrive in either order.

Deduplication

The same event can arrive more than once: after a retry, or when your server stored the event but answered too slowly. Record a key per event and skip one you have already handled.

Event order for subscriptions

AgentaOS checks each subscription with the card processor on a schedule and sends the events for what changed. The events below are what your endpoint receives. Unlock access on checkout.session.completed: it carries the metadata of the checkout, with your own ids. The checkout.session.completed for a renewal, or for the first charge after a trial, has its own session_id. Its metadata is AgentaOS’s own, not the metadata you set on the checkout, so your metadata.customerId is not on it. Match it to your user through metadata.subscriptionId, the subscription’s id, which is also on the first checkout event. The metadata of a renewal, and of the first charge after a trial, also has subscriptionCycle: true.

checkout.session.completed

Fires when:
  • A buyer pays a checkout by card, bank transfer or stablecoin.
  • A free trial starts: amount is "0" and trial is true.
  • A trial with a trial price starts: amount is the amount charged.
  • A later subscription charge succeeds: a renewal, the first charge after a trial, or an upgrade’s prorated charge.
  • A subscriber credit pays a renewal in full: amount is "0".
This is the event to listen for to fulfill an order. For the order of subscription events, see Event order for subscriptions.
The SDK’s CheckoutCompletedData type differs from the wire body in two ways. It types txHash, payer and linkId as string, but they are null in the cases above, so check for null. It does not declare rail, vendorReference, customerId, buyerEmail, buyerName, overpaidByCents, trial or trialEnd yet, although verify() returns them: read them with a cast, as shown in Payment SDK: Webhooks.
Example

send.completed

Fires when: an outbound stablecoin send that you started is confirmed.
Example

send.failed

Fires when: an outbound stablecoin send that you started fails: the broadcast fails, for example on a network error or an insufficient balance, or the transaction reverts on-chain.
Example
send.failed means the transaction never landed on-chain. A payment dispute or a card decline does not fire this event: those affect your balance directly. See Payouts.

Subscription events

Fires when:
  • subscription.created: the subscription becomes active or trialing for the first time: the buyer pays the first period, or saves a card for a trial.
  • subscription.renewed: a charge after the first one succeeds: a renewal, the first charge after a trial, or an upgrade’s prorated charge. A renewal that a subscriber credit pays also fires it. The first period does not fire it.
  • subscription.payment_failed: the status becomes past_due or unpaid: a renewal charge fails, including the first charge after a trial. It fires once when the status first moves there; a move from past_due to unpaid, and every later failed retry, sends nothing more.
  • subscription.updated: a cancel is scheduled or resumed (cancel_at_period_end), an upgrade is applied (new plan_name, link_id and amount_minor), a downgrade is scheduled (pending_plan set), a scheduled downgrade is reverted (pending_plan null again), or a scheduled downgrade takes over at the period end.
  • subscription.canceled: the status becomes canceled: at the period end after a scheduled cancel, or when the card processor ends the subscription for another reason. No more charges follow.
Subscription lifecycle events, delivered to your account’s webhook URL. All five share the same data shape. For the order they arrive in, see Event order for subscriptions.
Example

Dispute events

Fires when:
  • dispute.created: AgentaOS finds a new dispute on one of your sales.
  • dispute.closed: a dispute closes in your favor (status is won), or a bank inquiry closes without a chargeback (status is warning_closed). Either way the sale is released. A lost dispute sends no event: read it from the sale’s mor_status, which becomes charged_back.
A dispute starts when a buyer’s bank opens a chargeback on a sale, or first sends an inquiry about it (the warning_ statuses). Both events share the same data shape. transaction_id is the sale’s transaction id. For a one-time sale and for every subscription charge, it equals that charge’s checkout.session.completed id without the evt_ prefix, so keep those event ids and a dispute finds its sale, and for a renewal its metadata.subscriptionId. subscription.renewed cannot be matched to a dispute: its id is random and it carries no transaction id.
Example

account.updated

Fires when: a business’s verification changes, in live mode only.
  • Its identity check is verified or declined.
  • Our reviewers approve, reject, hold or resume the business, or ask for a change.
  • Our reviewers verify or withdraw its identity by hand.
The event goes to the business and to the platform that manages it. The body is the state after the change.
Example

webhook.test

Fires when: you click Send test event in Settings → Developers → Webhooks. Use it to check that your endpoint receives and verifies events. It goes to your account’s webhook URL, signed like every other event.
Example

Next steps

Verify signatures

How to register a URL and verify the HMAC-SHA256 signature, in TypeScript, Python, Go, and PHP.

Payment SDK: Webhooks

The webhooks resource in @agentaos/pay.

Platform webhooks

One endpoint for all the businesses you manage.