Learn how to accept notifications from Rainex to your server
Any change that happens to the system is captured as an event. These include changes relating to customers, subscriptions, plans, addons, etc.
Event logs relating to your project can be found on the UI under Logs > Event Logs. Every time a webhook is sent to your system the corresponding event is logged to this page.
For a better integration between Rainex and your application, Rainex provides you with webhooks. When configured, a webhook is used to send out an event notification to your service.
Once you've configured the URL, Rainex will post the event as a JSON to your webhook URL. For example, if a "subscription_activated" event occurs, then a notification is sent to the specified URL. You can configure webhook alerts to keep track of any events relating to your subscriptions, plans, addons and coupons.
When your application needs to know and act upon certain events when they occur in your Rainex account such as an account being canceled or a payment that failed, you can use webhooks to notify your application. Webhook notifications are usually posted asynchronously and so are not recommended for time-critical applications. When time is critical, it is better to use the Rainex API to check for events.
Rainex needs to get a status code 2XX reply from the configured URL to confirm that the notification sent via HTTP POST has been successfully delivered. If any webhook times out, Rainex will cancel and retry. Up to 6 retries happen for every webhook that fails and at exponential time intervals.
Every webhook that Rainex sends contains JSON body encoded with UTF-8. The body corresponds the following model:
interface Webhook {
id: string, //unique id if the event. You can use it as an idempotency key
webhookVersion: number, //will be 2 if you configure webhooks after 04.09.2024, 1 otherwise
eventDate: string, //ISO-8601 format date
content: any, //data of the event
eventName: string //what kind of event happened
}
The next chapter will explain the contains of the "content" field.
Data models
The "content" field of an incoming webhook will represent an object. Every field of this object will represent an entity related to the event happened. For example, if Rainex sends you a webhook when a subscription is activated, the "content" field will be an object with fields "customer" and "subscription". And if Rainex sends you a webhook when an invoice is generated, the "content" field will be an object with fields "customer" and "invoice".
Every entity has uniform model in webhooks. For example, Customer entity model will always contain the same fields as in "customer_created" webhook as in "subscription_created".
All possible entity models that you can receive via webhooks are described below.
Customer
interface Customer {
id: string;
firstName?: string;
lastName?: string;
email: string;
company?: string;
companyLinkedinUrl?: string;
phone?: string;
language?: string;
additionalEmails?: string[];
createdAt: string;
updatedAt?: string;
autoCollection?: string;
billingAddress?: CustomerBillingAddress;
contacts: CustomerContact[];
website?: string;
channel: string;
createdBy?: string;
lastUpdatedBy?: string;
}
Customer billing address
interface CustomerBillingAddress {
lastName?: string;
firstName?: string;
email?: string;
phone?: string;
companyName?: string;
house?: string;
street?: string;
apartment?: string;
city?: string;
zipCode?: string;
countryCode?: string;
country?: string;
stateCode?: string;
state?: string;
vatNumber?: string;
}
Customer Contact
interface CustomerContact {
id: string;
customerId: string;
lastName?: string;
firstName?: string;
email?: string;
phone?: string;
enabled: boolean;
}
Subscription
interface Subscription {
id: string;
customerId: string;
currencyCode: string;
productFamilyId: string;
usePendingPaymentFlow: boolean;
futureInvoiceDaysBeforeEndPeriod?: number;
daysNotifyAboutUnpaidInvoice?: number[];
startDate?: string;
activatedDate?: string;
nextBillingDate?: string;
channel: string;
billingCycles: string;
billingPeriod?: number;
autoCollection?: string;
status: string;
metadata: Record<string, string>;
mrr: number;
includeVat: boolean;
lineItems: SubscriptionLineItem[];
discounts: Discount[];
oneTimeCharges: OneTimeCharge[];
trialPeriod?: TrialPeriod;
frequency: Frequency;
initialBillingPeriod?: number;
createdAt: string;
updatedAt?: string;
cancellationDate?: string;
pendingPaymentInvoiceId?: string;
pendingPaymentReason?: string;
cancelledReason?: string;
cancelledCreditOption?: string;
version: number;
currentPeriodStartDate?: string;
hasSinglePaymentPlan: boolean;
hasScheduledChanges: boolean;
lastRenewalDate?: string;
isImported: boolean;
}
SubscriptionLineItem
interface SubscriptionLineItem {
id: string;
itemPriceId: string;
itemPriceName: string;
itemPriceExternalName: string;
freeQuantity?: number;
quantity?: number;
unitPrice?: number;
amount?: number;
chargeOnEvent?: string;
type: string;
isUsed: boolean;
createdAt?: string;
updatedAt?: string;
}
Discount
interface Discount {
id: number;
type: string;
applyOn: string;
durationType: string;
value: number;
itemPriceId?: string;
isUsed: boolean;
createdAt: string;
updatedAt?: string;
}
OneTimeCharge
interface OneTimeCharge {
id: string;
itemPriceId?: string;
itemPriceExternalName?: string;
itemPriceName?: string;
freeQuantity?: number;
quantity?: number;
amount?: number;
unitPrice?: number;
chargeOnEvent: string;
createdAt: Date;
appliedDiscounts?: AppliedDiscount[];
}
AppliedDiscount
interface AppliedDiscount {
id?: string;
type: string;
value: number;
}
TrialPeriod
interface TrialPeriod {
billingPeriod: number;
billingPeriodUnit?: string;
}
Frequency
interface Frequency {
unitOfMeasurement: string;
quantity: number;
id?: string;
}
Invoice
interface Invoice {
id?: string;
customerId?: string;
date?: string;
status?: string;
currencyCode?: string;
subscriptionId?: string;
issuedOn?: string;
paidOn?: string;
amountTotal?: number;
amountSubTotal?: number;
amountDiscount?: number;
amountAdjusted?: number;
amountPaid?: number;
amountCreditsApplied?: number;
amountDue?: number;
taxRate?: number;
amountTotalBeforeVat?: number;
amountVat?: number;
lineItems: InvoiceLineItem[];
linkedPayments: LinkedPayment[];
adjustmentCreditNotes: InvoiceCreditNote[];
issuedCreditNotes: InvoiceCreditNote[];
allocatedCredits: InvoiceAllocatedCredit[];
lineItemDiscounts: InvoiceLineItemDiscount[];
discounts: InvoiceDiscount[];
dueDate?: string;
singlePaymentId?: string;
}
InvoiceAllocatedCredit
interface InvoiceAllocatedCredit {
creditNoteId?: string;
creditNoteReason?: string;
creditNoteDate?: string;
creditNoteStatus?: string;
allocatedAmount?: number;
allocatedAt?: string;
}
InvoiceCreditNote
interface InvoiceCreditNote {
id?: string;
date?: string;
status?: string;
reason?: string;
total?: number;
}
InvoiceDiscount
interface InvoiceDiscount {
id?: string;
description?: string;
discountType?: string;
lineItemId?: string;
entityType?: string;
entityId?: string;
amount?: number;
}
InvoiceLineItemDiscount
interface InvoiceLineItemDiscount {
lineItemId?: string;
discountId?: string;
description?: string;
entityType?: string;
entityId?: string;
amount?: number;
}
LinkedPayment
interface LinkedPayment {
transactionId?: string;
transactionAmount?: number;
transactionStatus?: string;
transactionDate?: Date;
allocatedAmount?: number;
allocatedAt?: Date;
}
CreditNote
interface CreditNote {
type: string;
id: string;
customerId: string;
invoiceId: string;
currencyCode: string;
date: string;
status: string;
reason: string;
fractionalCorrection: number;
amountAllocated: number;
amountRefunded: number;
amountAvailable: number;
total: number;
lineItems: CreditNoteLineItem[];
allocations: CreditNoteAllocation[];
}
CreditNoteAllocation
interface CreditNoteAllocation {
invoiceId: string;
allocatedAmount: number;
allocatedAt: string;
}
CreditNoteLineItem
interface CreditNoteLineItem {
id: string;
description: string | null;
entityType: string | null;
entityId: string | null;
quantity: number;
unitAmount: number;
amount: number;
dateFrom: string;
dateTo: string;
}
Transaction
interface Transaction {
id: string | null;
type: string | null;
customerId: string | null;
status: string | null;
currencyCode: string | null;
date: string | null;
paymentMethod: string | null;
gateway: string | null;
referenceNumber: string | null;
amount: number | null;
allocatedAmount: number | null;
unusedAmount: number | null;
errorCode: string | null;
errorDescription: string | null;
refundedTransactionId: string | null;
referencedTransactionId: string | null;
}
Payment
interface Payment {
id: string | null;
type: string | null;
customerId: string | null;
status: string | null;
currencyCode: string | null;
date: string | null;
paymentMethod: string | null;
gateway: string | null;
referenceNumber: string | null;
amount: number | null;
allocatedAmount: number | null;
unusedAmount: number | null;
errorCode: string | null;
errorDescription: string | null;
refundedTransactionId: string | null;
referencedTransactionId: string | null;
allocations: PaymentAllocation[];
refundedAmount: number | null;
}
PaymentAllocation
interface PaymentAllocation {
invoiceId: string | null;
allocatedAmount: number | null;
}
Refund
interface Refund {
id: string | null;
type: string | null;
customerId: string | null;
status: string | null;
currencyCode: string | null;
date: string | null;
paymentMethod: string | null;
gateway: string | null;
referenceNumber: string | null;
amount: number | null;
allocatedAmount: number | null;
unusedAmount: number | null;
errorCode: string | null;
errorDescription: string | null;
refundedTransactionId: string | null;
referencedTransactionId: string | null;
refundType: string;
linkedCreditNotes: CreditNoteRefund[];
}
CreditNoteRefund
interface CreditNoteRefund {
creditNoteId: string;
transactionId: string;
transactionStatus: string;
amount: number;
}
ProductFamily
interface ProductFamily {
id: string;
name: string;
description: string | null;
channel: string;
includeVat: boolean | null;
updatedAt: string | null;
createdAt: string;
productType: string | null;
billingInfo: ProductFamilyBillingAddress | null;
brandingId: string | null;
}
ProductFamilyBillingAddress
interface ProductFamilyBillingAddress {
bankDetails: string | null;
email: string | null;
phone: string | null;
companyName: string | null;
house: string | null;
street: string | null;
apartment: string | null;
city: string | null;
zipCode: string | null;
countryCode: string | null;
country: string | null;
stateCode: string | null;
state: string | null;
vatNumber: string | null;
}
ProductFamilyItem
interface ProductFamilyItem {
id: string;
name: string;
externalName: string;
description: string | null;
productFamilyId: string;
channel: string;
metadata: { [key: string]: string; } | null;
enabledInPortal: boolean;
updatedAt: string | null;
createdAt: string | null;
type: string;
tags: string[] | null;
}
ProductFamilyItemPrice
interface ProductFamilyItemPrice {
id: string;
name: string;
externalName: string;
productFamilyId: string;
description: string | null;
pricingModel: string;
price: number | null;
projectFrequencyId: number | null;
currencyCode: string;
billingCycles: string;
billingPeriod: number | null;
freeQuantity: number | null;
metadata: { [key: string]: string; } | null;
trialPeriod: TrialPeriod | null;
planId: string | null;
addonId: string | null;
chargeId: string | null;
createdAt: string;
createdBy: string | null;
updatedAt: string | null;
lastUpdatedBy: string | null;
channel: string;
type: string;
isSinglePayment: boolean;
}
TrialPeriod
interface TrialPeriod {
billingPeriod: number;
billingPeriodUnit: string | null;
}
AttachedFamilyItem
interface AttachedFamilyItem {
id: string;
planId: string;
chargeId: string | null;
addonId: string | null;
type: string | null;
quantity: number | null;
chargeOnEvent: string | null;
createdAt: string;
updatedAt: string | null;
}
PaymentSource
interface PaymentSource {
id: string;
customerId: string;
gateway: string;
type: string;
primary: boolean;
createdAt: string;
}
SubscriptionChangeDetails
interface SubscriptionChangeDetails {
changeType: string;
}
SinglePayment
interface SinglePayment {
id: string;
customerId: string;
productFamilyId: string;
currencyCode: string;
autoCollection: string;
includeVat: boolean;
status: string;
paidOn: string | null;
canceledOn: string | null;
discounts: SinglePaymentDiscount[] | null;
items: SinglePaymentItem[] | null;
}
SinglePaymentItem
interface SinglePaymentItem {
id: string;
itemPriceId: string;
name: string;
pricingModel: string | null;
quantity: number | null;
unitPrice: number | null;
amount: number | null;
}
SinglePaymentDiscount
interface SinglePaymentDiscount {
id: string;
type: string;
applyOn: string;
value: number;
itemPriceId: string | null;
}
SubscriptionScheduledChanges
interface SubscriptionScheduledChanges {
subscriptionId: string;
invoiceId: string | null;
changesTrigger: string;
status: string;
lineItemChanges: LineItemChanges | null;
discountChanges: DiscountChanges | null;
appliedOn: string | null;
cancelledOn: string | null;
createdOn: string;
}
LineItemChanges
interface LineItemChanges {
deleteItemIds: string[] | null;
newItems: SubscriptionItemModel[] | null;
updateItems: SubscriptionItemModel[] | null;
}
SubscriptionItemModel
interface SubscriptionItemModel {
id: string;
itemPriceId: string;
freeQuantity: number | null;
quantity: number | null;
unitPrice: number | null;
amount: number | null;
type: string;
}
DiscountChanges
interface DiscountChanges {
deleteItemIds: string[] | null;
newItems: SubscriptionDiscountModel[] | null;
}
SubscriptionDiscountModel
interface SubscriptionDiscountModel {
type: string;
applyOn: string;
durationType: string;
value: number;
itemPriceId: string | null;
}
public class SubscriptionDiscountModel
{
public string Type { get; set; }
public string ApplyOn { get; set; }
public string DurationType { get; set; }
public double Value { get; set; }
public string? ItemPriceId { get; set; }
}
Events
Here you can find the list of all events that you will be notified about via webhooks. It includes description of when the event will occur and the models of "content" field for event.
customer_created
Occurs when a customer is imported, created via UI or API or registered via Customer Portal.
Content model
interface CustomerCreatedContent {
customer: Customer;
}
customer_changed
Occurs when a customer is updated by you via UI or API or has updated his own data via Customer Portal.
Content model
interface CustomerChangedContent {
customer: Customer;
}
customer_deleted
Occurs when a customer is deleted by you in UI or via API.
Content model
interface CustomerDeletedContent {
customer: Customer;
}
single_payment_created
Occurs when a Single Payment is created by you in UI or via API.
Content model
interface SinglePaymentCreatedContent {
customer: Customer;
singlePayment: SinglePayment;
}
single_payment_paid
Occurs when a Single Payment's invoice is fully paid.
Content model
interface SinglePaymentPaidContent {
customer: Customer;
singlePayment: SinglePayment;
}
single_payment_cancelled
Occurs when a Single Payment is cancelled via UI or API.
Content model
interface SinglePaymentCancelledContent {
customer: Customer;
singlePayment: SinglePayment;
}
subscription_created
Occurs when a Subscription is created via UI, API or Customer Portal.
Content model
interface SubsciptionCreatedContent {
customer: Customer;
subscription: Subscription;
}
subscription_started
Occurs when a Subscription's status is changed from "Future" to "Active", "NonRenewing", "InTrial" or "PendingPayment". It happens if you or the customer chose not to start subscription immediately upon subscription creation and the start date has come.
Content model
interface SubsciptionStartedContent {
customer: Customer;
subscription: Subscription;
}
subscription_activated
Occurs when a Subscription's status is changed from "Future", "InTrial", "Cancelled" or "PendingPayment" to "Active" or "NonRenewing". It happens when:
- You or the customer chose not to start subscription immediately upon subscription creation and the activation date has come
- The subscription has trial period and it has ended
- You chose to activate subscription only after receiving the first payment and the payment has been received
- You have created a subscription via UI or API and chose to activate it immediately
- You have configured your Customer Portal to activate new subscriptions immediately and a customer has subscribed via Customer Portal
- Subscription is renewed after the configured final action for the subscription's invoice has been taken.
Content model
interface SubsciptionActivatedContent {
customer: Customer;
subscription: Subscription;
}
subscription_changed
Occurs when a Subscription's parameters are changed. This includes:
- You or the customer have added, removed or updated any items in subscription with immediate application
- You or the customer have scheduled any changes to subscription for the next billing date
- You or the customer have cancelled changes scheduled for the next billing date
- You have added one time charge to the subscription
Content model
interface SubsciptionChangedContent {
customer: Customer;
subscription: Subscription;
subscriptionChangeDetails: SubscriptionChangeDetails;
}
subscription_trial_extended
Occurs when a Subscription's trial is extended, i.e. you have moved trial end date to a later one.
Content model
interface SubsciptionTrialExtendedContent {
customer: Customer;
subscription: Subscription;
}
subscription_trial_condensed
Occurs when a Subscription's trial length has reduced, i.e. you have moved trial end date to an earlier one.
Content model
interface SubsciptionTrialCondensedContent {
customer: Customer;
subscription: Subscription;
}
subscription_cancelled
Occurs when a Subscription's status became "Cancel". It happens when:
- You have set up invoices dunning and a subscription's invoice is still unpaid after all dunning retries and you have pointed in dunning settings that the final action after all dunning retries must be "cancel subscription"
- When a subscription has a fixed amount of billing cycles and all of them have expired
- When you or a customer have cancelled subscription via UI, API or Customer Portal
Content model
interface SubsciptionCancelledContent {
customer: Customer;
subscription: Subscription;
}
subscription_pending_payment
Occurs when a Subscription's status became "PendingPayment". It happens when:
- You have set up invoices dunning and a subscription's invoice is still unpaid after all dunning retries and you have pointed in dunning settings that the final action after all dunning retries must be "set subscription status to Pending Payment"
- You have created a subscription via UI or API and chose to activate it after payment
- You have configured your Customer Portal to activate new subscriptions after payment and a customer has subscribed via Customer Portal
Content model
interface SubsciptionPendingPaymentContent {
customer: Customer;
subscription: Subscription;
}
trial_started
Occurs when a Subscription's trial period has started.
Content model
interface TrialStartedContent {
customer: Customer;
subscription: Subscription;
}
trial_expiry
Occurs when a Subscription's trial period has ended.
Content model
interface TrialExpiryContent {
customer: Customer;
subscription: Subscription;
}
invoice_generated
Occurs when any invoice has been generated.
Content model
interface InvoiceGeneratedContent {
customer: Customer;
invoice: Invoice;
}
invoice_updated
Occurs when an invoice has been updated, i.e. one of the following:
- It's status has changed from "payment_due" to "paid". It may happen not only when the customer has paid an amount of money for the invoice, but also when the invoice has been fully covered by some credit notes and/or any positive balance that the customer had.
- When a payment is attached to invoice. It may happen when you pointed that the customer has paid some amount of money to you directly or when Rainex initiated a payment transaction to pay for the invoice.
- When a payment is detached from invoice. It occurs when customer successfully finishes an online payment for an invoice that is already paid.
- When a credit note is being attached to invoice. It includes:
- attaching some existing credit note to the invoice to reduce the due amount of it
- creating a refundable credit note to an already paid/partially paid invoice
- creating an adjustable credit note to an unpaid/partially paid invoice
Content model
interface InvoiceUpdatedContent {
customer: Customer;
subscription: Subscription;
}
credit_note_created
Occurs when you create a credit note via UI or API.
Content model
interface CrediteNoteCreatedContent {
customer: Customer;
creditNote: CreditNote;
}
credit_note_updated
Occurs when available amount of a credit note changes. It may happen when a credit note is attached to invoice to cover it's unpaid amount fully or partially and also when a refund transaction is created for a refundable credit note.
Content model
interface CreditNoteUpdatedContent {
customer: Customer;
creditNote: CreditNote;
}
credit_note_applied
Occurs when an invoice is generated and an existing credit note is being attached to the invoice to cover it's unpaid amount.
Content model
interface CreditNoteAppliedContent {
customer: Customer;
creditNote: CreditNote;
}
transaction_created
Occurs when a transaction in created within Rainex. It includes:
- Importing a subscription that has a payment
- An offline payment is created for an invoice/customer via UI or API
- Customer is paying online for an invoice
- When auto-collection is trigger in Rainex for an invoice (for that, the customer must have at least one payment method attached and subscription must be created with "Auto-collection: On")
- When invoice auto-collection dunning retry is triggered
- When a transaction is refunded online or offline
- When a refundable credit note is refunded online or offline
Content model
interface TransactionCreated {
customer: Customer;
transaction: Transaction;
}
transaction_updated
Occurs when a transaction's unused amount is changed, it's being allocated to an invoice, unallocated from invoice or it is being refunded.
Content model
interface TransactionUpdated {
customer: Customer;
transaction: Transaction;
}
payment_succeeded
Occurs when an online payment succeeds or an offline payment is created.f
Content model
interface PaymentSucceeded {
customer: Customer;
transaction: Payment;
}
payment_failed
Occurs when an online payment fails.
Content model
interface PaymentFailed {
customer: Customer;
transaction: Payment;
}
payment_initiated
Occurs when an online payment is initiated. It happens when another invoice auto-collection dunning attempt is performed, when a customer pays online and when Rainex is trying to initiate a payment for a subscription with "Auto-collection: On"
Content model
interface PaymentInitiated {
customer: Customer;
transaction: Payment;
}
refund_created
Occurs when an online refund is initiated or offline refund is recorded via UI or API.
Content model
interface RefundCreated {
customer: Customer;
transaction: Refund;
}
refund_completed
Occurs when an online refund is completed successfully or offline refund is recorded via UI or API.
Content model
interface RefundCompleted {
customer: Customer;
transaction: Refund;
}
refund_failed
Occurs when a online refund has failed.
Content model
interface RefundFailed {
customer: Customer;
transaction: Refund;
}
refund_cancelled
Occurs when a online refund has been cancelled.
Content model
interface RefundFailed {
customer: Customer;
transaction: Refund;
}
payment_source_added
Occurs when a customer obtains attached bank card/bank account that can be used for automatic payments.
Content model
interface PaymentSourceAddedContent {
customer: Customer;
paymentSource: PaymentSource;
}
payment_source_deleted
Occurs when a payment method is detached from customer.
Content model
interface PaymentSourceDeletedContent {
customer: Customer;
paymentSource: PaymentSource;
}
item_family_created
Occurs when a product family is created via API or UI.
Content model
interface ProductFamilyCreatedContent {
productFamily: ProductFamily;
}
item_family_updated
Occurs when a product family's info is updated via API or UI.
Content model
interface ProductFamilyUpdatedContent {
productFamily: ProductFamily;
}
item_family_deleted
Occurs when a product family is deleted via API or UI.
Content model
interface ProductFamilyDeletedContent {
productFamily: ProductFamily;
}
item_created
Occurs when a product family item (addon, plan, charge) is created via API or UI.
Content model
interface ProductFamilyCreatedContent {
productFamily: ProductFamily;
productFamilyItem: ProductFamilyItem;
}
item_updated
Occurs when a product family item (addon, plan, charge) is updated via API or UI.
Content model
interface ProductFamilyUpdatedContent {
productFamily: ProductFamily;
productFamilyItem: ProductFamilyItem;
}
item_deleted
Occurs when a product family item (addon, plan, charge) is deleted via API or UI.
Content model
interface ProductFamilyDeletedContent {
productFamily: ProductFamily;
productFamilyItem: ProductFamilyItem;
}
item_price_created
Occurs when a product family item's (addon's, plan's, charge's) price is created via API or UI.
Content model
interface ProductFamilyCreatedContent {
productFamilyItemPrice: ProductFamilyItemPrice;
}
item_price_updated
Occurs when a product family item's (addon's, plan's, charge's) price is updated via API or UI.
Content model
interface ProductFamilyUpdatedContent {
productFamilyItemPrice: ProductFamilyItemPrice;
}
item_price_deleted
Occurs when a product family item's (addon's, plan's, charge's) price is deleted via API or UI.
Content model
interface ProductFamilyDeletedContent {
productFamilyItemPrice: ProductFamilyItemPrice;
}
attached_item_created
Occurs when an addon or a charge is attached to a plan.
Content model
interface ProductFamilyCreatedContent {
attachedFamilyItem: AttachedFamilyItem;
}
attached_item_updated
Occurs when an attachment of a charge or an addon to a plan is updated
Content model
interface ProductFamilyUpdatedContent {
attachedFamilyItem: AttachedFamilyItem;
}
attached_item_deleted
Occurs when an addon or a charge is detached from a plan.
Content model
interface ProductFamilyDeletedContent {
attachedFamilyItem: AttachedFamilyItem;
}