Webhooks
Spinwheel webhooks provide asynchronous notifications when events or status changes occur within the Spinwheel platform. This guide covers how to configure, receive, and process webhook events.
Overview
Webhooks allow you to subscribe to Spinwheel events and receive updates as they occur, reducing the need to continuously poll Spinwheel APIs for status changes.
When a subscribed event occurs, Spinwheel sends a POST request to your configured endpoint containing information about the event. Requests can also include any custom headers configured for the webhook.
Leveraging Spinwheel Webhooks
Webhooks are best used to trigger downstream actions when an asynchronous Spinwheel workflow changes state.
A typical integration flow is:
- Subscribe to the webhook events relevant to your integration.
- Spinwheel sends an event to your configured endpoint when a subscribed event occurs.
- Use the event type and identifiers included in the payload to determine which user, transaction, payment, or other resource changed.
- Update your application's state or continue the appropriate workflow.
- When necessary, retrieve the associated resource from the Spinwheel API for the latest information.
Your webhook endpoint should also be designed to safely handle retries, as the same event may be delivered more than once.
Note: Spinwheel attempts to deliver each webhook up to 4 times. If the initial delivery fails, Spinwheel retries the webhook after approximately 5 minutes, 30 minutes, and 60 minutes using exponential backoff.
Retry attempts can be identified using the webhookId. For webhook IDs using the [epoch timestamp]-[retry attempt] format, the suffix identifies the delivery attempt. For example, 1773694304981-0 represents the initial delivery.
Whitelisting IPs
For each environment where these webhooks are consumed, certain IPs need to be whitelisted. Note the IPs listed per environment in the table below.
| Environment | IPs |
|---|---|
| Sandbox | 34.203.72.127 52.2.114.95 52.12.60.65 |
| Production | 44.232.30.137 3.230.55.249 |
Available Webhooks Reference Table
The current webhooks that can be subscribed to are as follows:
| Webhook Type | Summary | Related Products |
|---|---|---|
| SUBSCRIPTION_ACTIVATED | This webhook is triggered when a user is successfully enrolled in a Debt Profile Refresh Subscription. | Debt Profile Refresh Subscription |
| SUBSCRIPTION_FAILED | This webhook is triggered when a user fails to be enrolled in a Debt Profile Refresh Subscription. | Debt Profile Refresh Subscription |
| USER_CREDIT_PROFILE_TRANSACTION | This webhook is triggered based on latest Debt Profile Refresh Subscription renewal when there is a successful credit report pull. | Debt Profile Refresh Subscription |
| USER_CREDIT_PROFILE_TRANSACTION_FAILED | This webhook is triggered based on latest Debt Profile Refresh Subscription renewal when there is a failure to pull the credit report. | Debt Profile Refresh Subscription |
| REFRESH_TRANSACTION_STATUS | This webhook is triggered when a refresh liability status changes to either COMPLETED or FAILED. Please note this is specifically for the refresh liability functionality, not refresh user. | Real-TIme Liability Data |
| USER_PAYMENT_STATUS | This webhook emits updates regarding payment status changes for user transactions. | Payments |
| PLATFORM_PAYMENT_STATUS | This webhook is triggered when the payment request created by a Payment to Platform changes its state. | Payments |
| USER_REFINANCE_STATUS | This webhook is triggered when a refinance application status change is received for a user. (Note, it currently only supports a change to CONVERTED) | Refinance |
| BANK_ACCOUNT_LOOKUP_STATUS_CHANGE | This webhook is triggered when the status of a bank account information lookup transaction changes to either COMPLETED or FAILED | Bank Account |
| LIABILITY_GROUP_PAYOFF_QUOTE_STATUS_CHANGE | This webhook is triggered when the status of a student loan payoff quote lookup transaction changes to either COMPLETED or FAILED | Student Loan |
Payloads
Here are the expected payloads for each type of webhook:
SUBSCRIPTION_ACTIVATED Webhook
{
"eventType": "SUBSCRIPTION_ACTIVATED",
"userId": "3a35a0ba-9656-4b33-ac4f-2fa6dacae8a6",
"extUserId": "b1de1852-dc05-443a-8d13-bd81b4fdf006",
"subscriptionId": "28ddf73b-bd93-4c06-afa5-fd4e3994d23f",
"status": "COMPLETED", //status will always be COMPLETED for a success
"createdOn": 1708637591000,
"metadata": {
"creditReportType": "FULL",
"creditScoreModel": "EquifaxVantageScore3.0"
},
"bureau": "Equifax",
"webhookId": "1773694304981-0"
}SUBSCRIPTION_FAILED Webhook
{
"eventType": "SUBSCRIPTION_FAILED",
"userId": "3a35a0ba-9656-4b33-ac4f-2fa6dacae8a6",
"extUserId": "b1de1852-dc05-443a-8d13-bd81b4fdf006",
"subscriptionId": "28ddf73b-bd93-4c06-afa5-fd4e3994d23f",
"status": "REQUEST_FAILED", //status will always be REQUEST_FAILED for a failure
"createdOn": 1708637591000,
"metadata": {
"creditReportType": "FULL",
"creditScoreModel": "EquifaxVantageScore3.0"
},
"bureau": "Equifax",
"webhookId": "1773693912561-0"
}USER_CREDIT_PROFILE_TRANSACTION Webhook
{
"userId": "3a35a0ba-9656-4b33-ac4f-2fa6dacae8a6",
"extUserId": "b1de1852-dc05-443a-8d13-bd81b4fdf006",
"eventType": "USER_CREDIT_PROFILE_TRANSACTION",
"createdOn": 1708637591000,
"subscriptionId": "28ddf73b-bd93-4c06-afa5-fd4e3994d23f",
"status": "COMPLETED", // Or PENDING
"metadata": {
"creditReportType": "FULL",
"creditScoreModel": "EquifaxVantageScore3.0"
},
"bureau": "Equifax",
"webhookId": "1773694304981-0"
}USER_CREDIT_PROFILE_TRANSACTION_FAILED Webhook
{
"userId": "3a35a0ba-9656-4b33-ac4f-2fa6dacae8a6",
"extUserId":"b1de1852-dc05-443a-8d13-bd81b4fdf006",
"eventType":"USER_CREDIT_PROFILE_TRANSACTION_FAILED",
"createdOn":1708637591000,
"subscriptionId": "28ddf73b-bd93-4c06-afa5-fd4e3994d23f",
"status":"FROZEN_REPORT",//or "FRAUDULENT_REPORT" or "REPORT_FAILED"or "CREDIT_REPORT_NOT_FOUND" or "MANUAL_FILE" or "MANUAL_REVIEW_REQUIRED" or "REFERRED_FILE" or "LOCKED_REPORT"
"metadata": {
"creditReportType": "FULL",
"creditScoreModel": "EquifaxVantageScore3.0"
},
"bureau":"Equifax",
"webhookId": "1773694304981-0"
}REFRESH_TRANSACTION_STATUS Webhook
{
"eventType": "REFRESH_TRANSACTION_STATUS",
"userId": "b790770b-33c7-49d4-b086-e6e18864ba34",
"extRequestId": "28ddf73b-bd93-4c06-afa5-fd4e3994d23f",
"refreshTransactionId": "b790770b-33c7-49d4-b086-e6e18864ba34",
"creditCardId": "007035e0-7865-49f3-be50-c922b1c63dc6",
"refreshTransactionStatus": "COMPLETED", // or "FAILED"
"webhookId": "1710361341615-0",
"data": {
"balanceDetails": {
"outstandingBalance": 7000,
"updatedOn": 1597753517524
},
"statementSummary": {
"refreshedFields": {
"lastPaymentDate": {
"value": "2021-08-21",
"format": "YYYY-MM-DD",
"updatedOn": 1643917894780
},
"dueDay": {
"value": "08",
"format": "DD",
"updatedOn": 1643917894780
},
"lastPaymentAmount": {
"value": 400,
"updatedOn": 1643917894780
}
}
}
}
}USER_PAYMENT_STATUS Webhook
{
"userId": "e1b0d89d-6d86-4ff6-a2ab-46b99e2c1b1e",
"status": "SCHEDULED",
"statusComment": "Scheduled payment towards loan account",
"requestId": "a564cbf8-8669-481d-ad4b-82843462b31c",
"transactionRequestId": "c8301530-b77e-46c5-9c03-8d3233ff6b8d",
"transactionId": "f9bcb792-7af5-4eee-a561-3b6bed634556",
"eventType": "USER_PAYMENT_STATUS",
"liabilityType": "STUDENT_LOAN",
"webhookId": "1773694304981-0",
"paymentTraceNumber":"123456789",//for APPLIED/FAILED/RETURNED
"errorDescription":"Invalid account number provided for the account to be paid."// for FAILED/RETURNED
}PLATFORM_PAYMENT_STATUS Webhook
{
"employerPayerId": "e1b0d89d-6d86-4ff6-a2ab-46b99e2c1b1e",//for employment benefits only
"payerId": "c5377424-8122-4dc7-826c-5092197cb78a",//for non-employment benefits
"requestId": "db21f285-42b5-4382-b177-42d027acb6e3",
"transactionRequestId": "db21f285-42b5-4382-b177-42d027acb6e3",
"status": "SCHEDULED",
"statusComment": "Scheduled payment towards platform",
"eventType": "PLATFORM_PAYMENT_STATUS",
"webhookId": "1773694304981-0",
"tag": "Webhook"
}USER_REFINANCE_STATUS Webhook
{
"userId": "e1b0d89d-6d86-4ff6-a2ab-46b99e2c1b1e",
"externalUserId": "e1b0d89d-6d86-4ff6-a2ab-46b99e2c1b1e",
"applicationId": "e1b0d89d-6d86-4ff6-a2ab-46b99e2c1b1e",
"status": "PROCESSING",
"webhookId": "1773694304981-0",
"occurredOn": 1645245893901,
"details": {}
}BANK_ACCOUNT_LOOKUP_STATUS_CHANGE Webhook
{
"eventType": "BANK_ACCOUNT_LOOKUP_STATUS_CHANGE",
"webhookId": "1744732334424-0",
"status": "COMPLETED",
"transactionId": "41896b74-1b1c-461e-b311-a1d2202d3854",
"userId": "4f7fb087-d8d8-40a5-a39f-69ead67fcd8b",
"bankAccountId": "464e5005-4397-4abb-b4ec-00ee26600860",
"nextEligibleRefreshOn": 1744732357083,
"data": {
"accountBalance": 1700
}
}LIABILITY_GROUP_PAYOFF_QUOTE_STATUS_CHANGE Webhook
{
"webhookId": "1710361341615-0",
"eventType": "LIABILITY_GROUP_PAYOFF_QUOTE_STATUS_CHANGE",
"liabilityType": "STUDENT_LOAN",
"userId": "b790770b-33c7-49d4-b086-e6e18864ba34",
"extRequestId": "28ddf73b-bd93-4c06-afa5-fd4e3994d23f",
"refreshTransactionId": "3a3d045d-9b34-472a-9878-9d1d6f2f98da",
"liabilityGroupId": "c4188033-8462-41bb-901a-62329dd9bb92",
"refreshTransactionStatus": "COMPLETED | FAILED",
"nextEligibleRefreshOn": 1746053825213,
"studentLoanIds": ["039fc2c9-eacd-4db5-aedb-a85efa276116", "983e7b73-bf7b-4c0d-b849-6cd7c7945f46"],
"data": {
"payoffAmount": 28014,
"payoffGoodThroughDate": "2025-05-30",
"updatedOn": 1745621877124
}
}Updated 5 days ago

