Available Events
| Event Name | Trigger | Content | Sample Payload | |
|---|---|---|---|---|
| transactionmessage.created | Whenever a new Transaction Message is registered in the Astrada system | A complete understanding of the created Transaction Message object | See here | |
| transaction.created | Whenever a new Transaction is created in the Astrada system | References to the transaction object and its related entities | See here | |
| transaction.updated | Whenever a Transaction is updated in the Astrada system | References to the updated transaction object and its related entities | See here | |
| banklink.completed | Whenever a bank-link enrollment completes | The completed bank link and the bank accounts discovered under it | See here | |
| bankaccount.state_changed | Whenever a linked bank account's connection state changes | The bank account with its new and previous state, and any re-auth reason | See here | |
| banktransaction.created | Whenever a bank transaction is synced from a linked bank account | The created bank transaction | See here | |
| transaction.match.created | Whenever a bank transaction is matched to a card transaction | The match with its confidence, scoring reasons, and both matched sides | See here | |
| cardsubscription.created | Whenever a Card Subscription is created in the Astrada system | Reference to the created card subscription | See here | |
| cardsubscription.updated | Whenever a Card Subscription is updated in the Astrada system | Reference to the updated card subscription | See here | |
| networkbulkfeed.statechanged | Whenever a Network Bulk Feed changes state | Reference to the network bulk feed and the new and old states | See here | |
| enrichment.merchant.created | Whenever a Transaction Message is enriched with Merchant data | A complete understanding of the created Merchant Enrichment | See here | 🧪 |
🧪 Experimental Feature — behavior may change.
Sample Payloads
Alongside the payload that is sent in HTTP request body (in JSON format), an HTTP header (webhook-event-type) is also present that allows to infer the event type.
transactionmessage.created
Payload is identical to the GET Transaction Message endpoint
transaction.created
Payload consists of links to the created transaction and its related entities.
{
"_links": {
"self": {
"href": "/transactions/884820d4-1b11-4dfd-ab83-988f754712da"
},
"subaccount": {
"href": "/subaccounts/c6d5e036-361e-4773-a514-b9496cf2d2b5"
},
"card": {
"href": "/cards/4d1ff59f-4286-4209-9662-92e174193562"
},
"messages": [
{
"href": "/transaction-messages/f4b24a0a-6a37-4ce3-8845-ddf0b604a9b4"
}
]
},
"acceptor": {
"city": "LONDON",
"country": "GBR",
"mcc": "5734",
"state": "LND"
},
"cardId": "4d1ff59f-4286-4209-9662-92e174193562",
"cardholderBillingCurrency": "GBP",
"cardholderBillingHoldAmount": 0,
"cardholderBillingSettledAmount": 0.81,
"createdAt": "2024-05-01T06:41:43.810Z",
"descriptor": "Uber",
"id": "884820d4-1b11-4dfd-ab83-988f754712da",
"network": "MASTERCARD",
"status": "SETTLED",
"subaccountId": "c6d5e036-361e-4773-a514-b9496cf2d2b5",
"transactionCurrency": "USD",
"transactionHoldAmount": 0,
"transactionSettledAmount": 1,
"transactionType": "DEBIT_01",
"updatedAt": "2024-05-02T08:41:43.810Z"
}Augmenting transaction.created with a projection of transaction messages data
Transaction message data is included as part of the transaction.created webhook by default. An array containing all correlated messages is added to the transaction aggregate payload inside the _embedded field. Example:
{
"_embedded": {
"messages": [
{
"_links": {
"self": {
"href": "/transaction-messages/f4b24a0a-6a37-4ce3-8845-ddf0b604a9b4"
}
},
"approvalCode": "537254",
"cardholderBillingAmount": 1.18,
"cardholderBillingCurrency": "GBP",
"dateTime": "2024-04-24T13:39:45",
"id": "f4b24a0a-6a37-4ce3-8845-ddf0b604a9b4",
"messageType": "FINL_ADVC",
"network": "MASTERCARD",
"result": "APPROVED",
"transactionAmount": 1.45,
"transactionCurrency": "USD",
"transactionReference": "IWVQ22_2024-04-24"
}
]
}
}This expanded payload is enabled by default. If your integration cannot accept the _embedded projection, reach out to your Astrada Account Manager or [email protected] to have it disabled.
transaction.updated
Payload consists of links to the updated transaction and its related entities.
{
"_links": {
"self": {
"href": "/transactions/884820d4-1b11-4dfd-ab83-988f754712da"
},
"subaccount": {
"href": "/subaccounts/c6d5e036-361e-4773-a514-b9496cf2d2b5"
},
"card": {
"href": "/cards/4d1ff59f-4286-4209-9662-92e174193562"
},
"messages": [
{
"href": "/transaction-messages/f4b24a0a-6a37-4ce3-8845-ddf0b604a9b4"
},
{
"href": "/transaction-messages/934f8701-53e3-4a2b-a000-6bb52195d2ea"
}
]
},
"acceptor": {
"city": "LONDON",
"country": "GBR",
"mcc": "5734",
"state": "LND"
},
"cardId": "4d1ff59f-4286-4209-9662-92e174193562",
"cardholderBillingCurrency": "GBP",
"cardholderBillingHoldAmount": 0,
"cardholderBillingSettledAmount": 0.81,
"createdAt": "2024-05-01T06:41:43.810Z",
"descriptor": "Uber",
"id": "884820d4-1b11-4dfd-ab83-988f754712da",
"network": "MASTERCARD",
"status": "SETTLED",
"subaccountId": "c6d5e036-361e-4773-a514-b9496cf2d2b5",
"transactionCurrency": "USD",
"transactionHoldAmount": 0,
"transactionSettledAmount": 1,
"transactionType": "DEBIT_01",
"updatedAt": "2024-05-02T08:41:43.810Z"
}Augmenting transaction.updated with a projection of transaction messages data
Transaction message data is included as part of the transaction.updated webhook by default. An array containing all correlated messages is added to the transaction aggregate payload inside the _embedded field. Example:
{
"_embedded": {
"messages": [
{
"_links": {
"self": {
"href": "/transaction-messages/f4b24a0a-6a37-4ce3-8845-ddf0b604a9b4"
}
},
"approvalCode": "537254",
"cardholderBillingAmount": 1.18,
"cardholderBillingCurrency": "GBP",
"dateTime": "2024-04-24T13:39:45",
"id": "f4b24a0a-6a37-4ce3-8845-ddf0b604a9b4",
"messageType": "FINL_ADVC",
"network": "MASTERCARD",
"result": "APPROVED",
"transactionAmount": 1.45,
"transactionCurrency": "USD",
"transactionReference": "IWVQ22_2024-04-24"
}
]
}
}This expanded payload is enabled by default. If your integration cannot accept the _embedded projection, reach out to your Astrada Account Manager or [email protected] to have it disabled.
Bank-sourced activity (bank linking)
When a bank account is linked, bank-observed money movement rides the SAME events documented above — there are no new event types or payload shapes to integrate. Three things are worth knowing:
1. Bank-only transactions. A bank movement with no card counterpart (payroll, transfers, fees, FX markup — and, on a card-less bank link, everything) arrives as a transactionmessage.created carrying a synthetic FINL_ADVC, followed by a transaction.created for the new SETTLED aggregate. The universal markers are: no approvalCode, a bank_-prefixed transactionReference, and a bankData block. A bank-only movement always carries network: "OPEN_BANKING" — it never adopts a card network. On a card-less account it also carries cardId: null (_links.card omitted); on an account with linked cards it is attributed to the account's oldest linked card and carries that card's cardId (for feed grouping only — the network stays "OPEN_BANKING").
2. Earlier settlement. When a bank posting matches one of your card transactions with high confidence, the transaction settles early: a bank-sourced FINL_ADVC (inheriting the auth's transactionReference, approvalCode, and network) and a transaction.updated flipping PENDING→SETTLED — typically hours after the swipe instead of days. When the card network's own clearing arrives later, the settled amounts may revise once more (tips, FX): the network remains the financial authority. Amount revision on transaction.updated is expected behavior, not an error.
3. Bank-first, card-later. If the bank movement arrived first as a standalone transaction and card data shows up later, the movement is re-settled onto the card transaction and the standalone's transaction.updated revises its settled amounts to 0 (status stays SETTLED). No new field or status to handle — consumers that already process amount revisions get this for free. Re-matching of late card data runs on a scheduled cadence (tight in the first hours, then progressively less frequent across the 14-day match window), and the card transaction's settlement and the standalone's netting revision ride independent stream partitions — they can arrive in either order. Key state by bankData.bankTransactionId and treat each event as an idempotent upsert, and both properties are harmless.
Linking the surfaces. bankData.bankTransactionId (on bank-sourced transactionmessage.created payloads and the _embedded.messages[] projection) equals banktransaction.created.id and transaction.match.created.matches[].id, and resolves via GET /bank-transactions/{subaccountId}/{id} — one join key across every bank-data surface, no extra REST calls needed to correlate push events.
A bank-sourced embedded message carries the join key in its bankData block (deliberately slim — the bank's merchant string, dates and amounts already map into the message's canonical fields; personalFinanceCategory is the one bank-only datum with no card-side equivalent):
{
"bankData": {
"provider": "plaid",
"bankTransactionId": "7f2a9c4e-3b1d-4e8f-a5c7-6d0e2f9b8a3c",
"personalFinanceCategory": {
"primary": "FOOD_AND_DRINK",
"detailed": "FOOD_AND_DRINK_RESTAURANT"
}
}
}That bankTransactionId is the id of the corresponding banktransaction.created event (and matches[].id on transaction.match.created), so you can stitch the bank-feed events and this unified transaction into one record with no extra call.
Dedicated bank events. Beyond the transaction.* feed above, the banking service emits the four events below directly, and they can be subscribed to independently — the bank-linking lifecycle (banklink.completed, bankaccount.state_changed) and the bank-side records (banktransaction.created, transaction.match.created). They share the bank-transaction id join key described above.
banklink.completed
Sent when a bank-link enrollment finishes — via the manual PATCH /bank-links/{bankLinkId} completion or the hosted-link flow (Plaid SESSION_FINISHED plus the polling fallback). The payload carries the completed bankLinkId and the bank accounts discovered under it, so a push-only consumer can react to a new connection without polling GET /bank-links.
{
"bankLinkId": "enrollment_792dcb7d",
"bankAccounts": [
{
"id": "3a8f2c1d-5e7b-4d9a-b6c8-9f0e1d2a3b4c",
"name": "Checking"
}
]
}bankaccount.state_changed
Sent whenever a linked bank account's connection state actually changes — to auth_required (with a reason and, when known, an expiresAt), to disconnected, or back to active on recovery. Integrators can prompt the end user to re-authenticate — and stop prompting — without polling GET /bank-accounts. state is one of active, auth_required, or disconnected; reason and expiresAt are null unless applicable.
{
"bankAccountId": "3a8f2c1d-5e7b-4d9a-b6c8-9f0e1d2a3b4c",
"state": "auth_required",
"previousState": "active",
"reason": "consent_expiring",
"expiresAt": "2026-07-09T00:00:00.000Z"
}banktransaction.created
Sent when a bank transaction is synced from a linked account (via Plaid sync). Its id is the bank-transaction identifier that threads through every bank-data surface — it equals transaction.match.created.matches[].id and the bankData.bankTransactionId on the card feed, and resolves via GET /bank-transactions/{subaccountId}/{id}. amount is always positive — direction is carried by transactionType (debit or credit). category is the primary personal-finance category (or null) — note the REST GET /bank-transactions resource exposes category as an array of provider categories instead; merchantName may be null.
{
"id": "7f2a9c4e-3b1d-4e8f-a5c7-6d0e2f9b8a3c",
"bankAccountId": "3a8f2c1d-5e7b-4d9a-b6c8-9f0e1d2a3b4c",
"bankAccountName": "Checking",
"date": "2025-10-15",
"amount": 42.5,
"currency": "USD",
"description": "UBER TRIP",
"merchantName": "Uber",
"category": "Travel",
"pending": false,
"transactionType": "debit"
}transaction.match.created
Sent when the matching engine links a bank transaction to one of your card transactions. The payload includes the match's own matchId (address it at GET /transaction-matches/{subaccountId}/{matchId}; the REST resource exposes the same value as its top-level id), the confidence (HIGH ≥ 0.70, MEDIUM ≥ 0.50, LOW ≥ 0.20) and numeric score, the per-factor reasons behind the score, a summary of the matched card transaction, and the matched bank transaction(s) under matches[]. Each matches[].id is the bank-transaction id — the shared join key across the bank-data surfaces.
{
"matchId": "b1c2d3e4-f5a6-7b8c-9d0e-1f2a3b4c5d6e",
"confidence": "HIGH",
"score": 0.88,
"cardTransaction": {
"id": "9c8b7a6d-5e4f-3c2b-1a0d-9e8f7c6b5a4d",
"cardId": "5dec2c49-0aa5-4683-a317-427eb5d115f3",
"date": "2025-10-15",
"amount": 42.5,
"currency": "USD",
"descriptor": "UBER *TRIP",
"source": "Card"
},
"reasons": [
{
"type": "Amount",
"score": 1,
"cardValue": 42.5,
"bankValue": 42.5,
"diff": 0,
"message": "Exact match"
},
{
"type": "Date",
"score": 1,
"cardValue": "2025-10-15",
"bankValue": "2025-10-15",
"diff": 0,
"message": "Exact match"
},
{
"type": "Merchant",
"score": 0.88,
"cardValue": "UBER *TRIP",
"bankValue": "Uber",
"diff": 12,
"message": "88% similarity"
}
],
"matches": [
{
"id": "7f2a9c4e-3b1d-4e8f-a5c7-6d0e2f9b8a3c",
"bankAccountId": "3a8f2c1d-5e7b-4d9a-b6c8-9f0e1d2a3b4c",
"bankAccountName": "Checking",
"date": "2025-10-15",
"amount": 42.5,
"currency": "USD",
"source": "Plaid",
"description": "UBER TRIP"
}
]
}cardsubscription.created
Payload consists of links to the created subscription.
For cardholder-single enrollments, networkBulkFeedId is null and the networkBulkFeed link is not present:
{
"_links": {
"card": {
"href": "/cards/94b9b0ce-5775-470d-855e-0c0d0e72b0ea"
},
"self": {
"href": "/card-subscriptions/aadf6c89-0356-4d94-8fa8-b5465077a0fb"
}
},
"cardId": "94b9b0ce-5775-470d-855e-0c0d0e72b0ea",
"createdAt": "2024-09-02T09:42:39.678Z",
"customerReferenceId": null,
"effectiveDate": "2024-09-02T09:42:39.677Z",
"enrollmentType": "cardholder-single",
"expirationDate": "2025-09-02T09:42:43.270Z",
"id": "aadf6c89-0356-4d94-8fa8-b5465077a0fb",
"networkBulkFeedId": null,
"state": "reqSCA",
"subaccountId": "6103874b-248d-4825-af88-a0d24dd9b123",
"updatedAt": "2024-09-02T09:42:43.576Z"
}For network-bulk enrollments, networkBulkFeedId and the networkBulkFeed link are included:
{
"_links": {
"card": {
"href": "/cards/94b9b0ce-5775-470d-855e-0c0d0e72b0ea"
},
"networkBulkFeed": {
"href": "/network-bulk-feeds/5ccc9922-e763-4492-b693-b6a922d96049"
},
"self": {
"href": "/card-subscriptions/aadf6c89-0356-4d94-8fa8-b5465077a0fb"
}
},
"cardId": "94b9b0ce-5775-470d-855e-0c0d0e72b0ea",
"createdAt": "2024-09-02T09:42:39.678Z",
"customerReferenceId": null,
"effectiveDate": "2024-09-02T09:42:39.677Z",
"enrollmentType": "network-bulk",
"expirationDate": "2025-09-02T09:42:43.270Z",
"id": "aadf6c89-0356-4d94-8fa8-b5465077a0fb",
"networkBulkFeedId": "5ccc9922-e763-4492-b693-b6a922d96049",
"state": "active",
"subaccountId": "6103874b-248d-4825-af88-a0d24dd9b123",
"updatedAt": "2024-09-02T09:42:43.576Z"
}cardsubscription.updated
Payload consists of links to the updated subscription.
For cardholder-single enrollments:
{
"_links": {
"card": {
"href": "/cards/94b9b0ce-5775-470d-855e-0c0d0e72b0ea"
},
"self": {
"href": "/card-subscriptions/aadf6c89-0356-4d94-8fa8-b5465077a0fb"
}
},
"cardId": "94b9b0ce-5775-470d-855e-0c0d0e72b0ea",
"createdAt": "2024-09-02T09:42:39.678Z",
"customerReferenceId": null,
"effectiveDate": "2024-09-02T09:42:39.677Z",
"enrollmentType": "cardholder-single",
"expirationDate": "2025-09-02T09:42:43.270Z",
"id": "aadf6c89-0356-4d94-8fa8-b5465077a0fb",
"networkBulkFeedId": null,
"state": "active",
"subaccountId": "6103874b-248d-4825-af88-a0d24dd9b123",
"updatedAt": "2024-09-02T10:01:44.176Z"
}For network-bulk enrollments:
{
"_links": {
"card": {
"href": "/cards/94b9b0ce-5775-470d-855e-0c0d0e72b0ea"
},
"networkBulkFeed": {
"href": "/network-bulk-feeds/5ccc9922-e763-4492-b693-b6a922d96049"
},
"self": {
"href": "/card-subscriptions/aadf6c89-0356-4d94-8fa8-b5465077a0fb"
}
},
"cardId": "94b9b0ce-5775-470d-855e-0c0d0e72b0ea",
"createdAt": "2024-09-02T09:42:39.678Z",
"customerReferenceId": null,
"effectiveDate": "2024-09-02T09:42:39.677Z",
"enrollmentType": "network-bulk",
"expirationDate": "2025-09-02T09:42:43.270Z",
"id": "aadf6c89-0356-4d94-8fa8-b5465077a0fb",
"networkBulkFeedId": "5ccc9922-e763-4492-b693-b6a922d96049",
"state": "active",
"subaccountId": "6103874b-248d-4825-af88-a0d24dd9b123",
"updatedAt": "2024-09-02T10:01:44.176Z"
}networkbulkfeed.statechanged
Webhook payload consists of a link to the related entity and the new and old states.
{
"_links": {
"self": {
"href": "/network-bulk-feeds/884820d4-1b11-4dfd-ab83-988f754712da"
}
},
"createdAt": "2024-05-01T06:41:43.810Z",
"id": "884820d4-1b11-4dfd-ab83-988f754712da",
"network": "MASTERCARD",
"networkReference": "G234621",
"newState": "active",
"oldState": "submitted",
"subaccountId": "c6d5e036-361e-4773-a514-b9496cf2d2b5",
"updatedAt": "2024-05-02T08:41:43.810Z"
}When a bulk feed transitions to the failed state, an errorReason field is included in the payload. This currently only applies to VISA bulk feeds.
{
"_links": {
"self": {
"href": "/network-bulk-feeds/a23bb1e5-2bb9-4472-be8b-a500e21c8a42"
}
},
"createdAt": "2026-04-08T22:54:32.111Z",
"errorReason": "A bad request error occurred while requesting starter data: \"789452INVALID: Your Company ID is not a numeric value. Please provide a valid company ID!; No records found for the given inputs. Please provide valid inputs!\"",
"id": "a23bb1e5-2bb9-4472-be8b-a500e21c8a42",
"network": "VISA",
"networkReference": "1_1_9999_789452INVALID",
"newState": "failed",
"oldState": "submitted",
"subaccountId": "2f394ae7-5eef-4dfa-b3c3-0e973ae2ec51",
"updatedAt": "2026-04-08T22:54:32.111Z"
}When a bulk feed was created with expectedCardCount, the value is included on every webhook payload for that feed. Absent when the feed was created without it.
{
"_links": {
"self": {
"href": "/network-bulk-feeds/884820d4-1b11-4dfd-ab83-988f754712da"
}
},
"createdAt": "2024-05-01T06:41:43.810Z",
"id": "884820d4-1b11-4dfd-ab83-988f754712da",
"network": "MASTERCARD",
"networkReference": "G234621",
"newState": "active",
"expectedCardCount": 5000,
"oldState": "submitted",
"subaccountId": "c6d5e036-361e-4773-a514-b9496cf2d2b5",
"updatedAt": "2024-05-02T08:41:43.810Z"
}enrichment.merchant.created
{
"_links": {
"message": {
"href": "/transaction-messages/884820d4-1b11-4dfd-ab83-988f754712da"
},
"merchant": {
"href": "https://www.amazon.com",
"title": "Amazon"
},
"merchant-logo": {
"href": "https://static.v2.spadeapi.com/logos/5f35110e8de74f9cadc6b28bf87dd5b6/light.png",
"type": "image/png",
"title": "Amazon logo"
}
},
"id": "6fb8303a-3a91-41d1-a56d-5056cc7e84a9",
"createdAt": "2025-10-20T17:38:317Z",
"merchant": {
"name": "Amazon",
"category": "Online Marketplace"
},
"location": {
"address": "1234 W 5th Ave Suite 100",
"city": "New York",
"state": "NY",
"country": "USA",
"postalCode": "10001",
"phoneNumber": "+18664862360"
}
}