Skip to main content

Merchant Webhooks

Each installment plan event has a corresponding webhook event provided by Splitit. When you subscribe to an event, an asynchronous call is made to your predefined endpoint from the Splitit servers. This call will be fired to your endpoint every hour, for 24 hours, until you reply with HTTP code 200.

CreateSucceeded

The only event that you can subscribe to directly by API is CreateSucceeded, which notifies you that a call to the Create API finished positively, i.e. payment went through (this could be either just an authorization or an authorization and a capture). CreateSucceeded is useful in cases when a payment has succeeded on Splitit's end but for some reason your application fails to redirect to your success page in response. Thus it isn't clear to you whether the operation was successful. The CreateSucceeded webhook will notify you that payment was successful, allowing you to finalize the order on your end.

The URL you provide will be concatenated with the unique installment plan number parameter and the order number sent originally in the Initiate request. For example: [CreateSucceededURL]?RefOrderNumber=123456&InstallmentPlanNumber=111222333444555. This URL will be called each hour for 24 hours until an HTTP response of 200 is returned from the caller.

To subscribe to CreateSucceeded, include the following within the EventsEndpoints object when you call Initiate.

"EventsEndpoints": {
"CreateSucceeded": "the URL to call"
}

Other Events with Webhooks (configurable by Splitit support)

See the Hub docs.

Signature Validation for Added Security

All outgoing webhooks have an idempotency key in their headers, "X-Splitit-IdempotencyKey," along with a signature, "X-Splitit-Signature." The signature is calculated by concatenating the idempotency key, a semicolon and the body of the webhook in the form KEY;BODY.

You can validate the signature with Python:

Signature Validation with Python
   import base64
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography import x509

# --- Splitit public certificate (PEM) --- (find here for prod: https://webhooks-v2.splitit.com/api/v1/auth/public-keys and find here for sandbox: https://webhooks-v2.sandbox.splitit.com/api/v1/auth/public-keys)
CERT_PEM = """-----BEGIN CERTIFICATE-----
MIIDBTCCAb2gAwIBAgIJAPSm5WApGIbtMD0GCSqGSIb3DQEBCjAwoA0wCwYJYIZI
AWUDBAICoRowGAYJKoZIhvcNAQEIMAsGCWCGSAFlAwQCAqIDAgEwMBIxEDAOBgNV
BAMTB1NwbGl0aXQwHhcNMjUwNTE0MTUwMTQ4WhcNMjYwNTE0MTUwMTQ4WjASMRAw
DgYDVQQDEwdTcGxpdGl0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
3x4hWL5PufM6BMSOStqwexC8Bx4AJnn9mQxbDWKw1qTNi6qJR2TDUiBxRlX9z8Ws
X/zWNK4DPO+9wC6ZTYW2uUjbNHKSCYLgA8Nc7Zg4Zg165MtrBhZwd5Ot0vkI1DLI
wO++RzBLyb7QeISK2NRz4I9c17U0Weqk5n4KVv8Qecmhyeeoe8U1tb4NR/x256Mf
JMOHvKMDy9I0p8HjIYuFXzQoQCoEjVuyk78amyAz+mrKO1RUzZlZCRx0mbQK9Sir
9X2Tpe6A4XH/r2K1JHDgTHM7+f4ZPN4lO0PQQGFvwTify7DVHxRnRaEJ473vdAXU
SBG8CFw7Mm+qwtwShIl+GQIDAQABMD0GCSqGSIb3DQEBCjAwoA0wCwYJYIZIAWUD
BAICoRowGAYJKoZIhvcNAQEIMAsGCWCGSAFlAwQCAqIDAgEwA4IBAQBLXw+MsR0V
PBaA9O/3DT8qAM7CDNuF59RRBd6XOWanIEwqz14Dxp2qodn1cjr0iUKvLe9g2WJH
lEsTYbfxiL57KAGeue9UrZtjoPfOaOYtGu/x55DC0wUSDORl03vOZUiOE0dns0HA
m5GMvM9jJisn71B+wjqHcn2IH3B3PPKNx6iZC7/eJgIt7xstX1k0DIP6/lSLGSaT
rzCLmliRqjCV+WGEl/m4eNXsA0bbdYsFGj2qcqWqOWZWJTykwFnoDrpcyit0OMag
2DPpTFirR7NVpp45IP0E6X6YHvOLUUcAd6tztFlWt7dc1yuXStbmlTMM/qQhPhbe
0ymn5Fao4bfX
-----END CERTIFICATE-----"""

# --- Example inputs ---
IDEMPOTENCY_KEY = "6b3ef735844f4fac9c53b131b770af9a6388575177543093588e459a8139d64e6cbf985fd3b6462d2a"
BODY = (
'{"InstallmentPlanEventType":"PlanCreatedSucceeded","InstallmentPlan":{"InstallmentPlanNumber":"0XJS76G9N73GQU49E3E0","InstallmentPlanStatus":{"Id":3,"Code":"InProgress","Description":"In Progress"},"Amount":{"Value":1593.00,"Currency":{"Symbol":"€","Id":4,"Code":"EUR","Description":"Euro"}},"OutstandingAmount":{"Value":1593.00,"Currency":{"Symbol":"€","Id":4,"Code":"EUR","Description":"Euro"}},"NumberOfInstallments":2,"NumberOfProcessedInstallments":0,"OriginalAmount":{"Value":1593.00,"Currency":{"Symbol":"€","Id":4,"Code":"EUR","Description":"Euro"}},"RefundAmount":{"Value":0.00,"Currency":{"Symbol":"€","Id":4,"Code":"EUR","Description":"Euro"}},"Consumer":{"Id":"525c332c-4742-45a5-bf54-2db47935c548","UniqueId":"525c332c-4742-45a5-bf54-2db47935c548","UserName":"aASAS@sada.com","FullName":"adasd dads","Email":"aASAS@sada.com","PhoneNumber":"8457656","CultureName":"pt-PT","RoleName":null,"IsLocked":false,"IsDataRestricted":false,"IsDataPrivateRestricted":false},"ActiveCard":{"CardId":"WdCexD3eTJelpBgvOLomwk95DDYlJfJO9EJ","CardNumber":"************1111","CardExpMonth":null,"CardExpYear":null,"CardBrand":{"Id":2,"Code":"Visa","Description":"VISA"},"CardType":{"Id":1,"Code":"Credit","Description":"CREDIT"},"Bin":"411111","CardHolderFullName":"a**** d***","CardCvv":"[Filtered]","Address":{"AddressLine":"qweqweqw","AddressLine2":null,"City":"portimao","Country":"PT","State":null,"Zip":"8500-112","FullAddressLine":"qweqweqw,portimao,PT"},"Token":null,"FpanLast4Digits":null},"FraudCheck":{"FraudCheckResult":{"Id":3,"Code":"NotReviewed","Description":"Not Reviewed"}},"Terminal":{"NewId":"SPL_000054742","ApiKey":"0859bab9-3ce9-4568-9353-b623fb53280f","Id":-1,"Code":"SPL_000054742","Description":"BlueSnapDirect"},"Merchant":{"Name":"Emma Sleep Test","NewId":"SPL_000054742","MerchantFacingName":"Emma Sleep Test","Id":-1,"Code":"SPL_000054742","Description":"Emma Sleep Test"},"RefOrderNumber":"0015-VBW59J","PurchaseMethod":{"Id":3,"Code":"ECommerce","Description":"E-Commerce"},"Strategy":{"Id":1,"Code":"SecuredPlan","Description":"Secured"},"DelayResolution":null,"ExtendedParams":{"userAgent":"node","ipAdd'+'ress":"..f'+'fff.1'+'27.'+'0.0.6"},"IsFullCaptured":false,"IsChargedBack":false,"ArePaymentsOnHold":false,"ScpFundingPercent":0.0,"FundingStatus":"NotDetermined","TestMode":"None","CreationDateTime":"2025-06-17T10:09:34.867","LifeTimeUrlExpirationTime":"2025-06-24T10:09:34.867","Installments":[{"InstallmentId":"14688634","InstallmentNumber":1,"Amount":{"Value":796.50,"Currency":{"Symbol":"€","Id":4,"Code":"EUR","Description":"Euro"}},"OriginalAmount":{"Value":796.50,"Currency":{"Symbol":"€","Id":4,"Code":"EUR","Description":"Euro"}},"RefundAmount":{"Value":0.00,"Currency":{"Symbol":"€","Id":4,"Code":"EUR","Description":"Euro"}},"ProcessDateTime":"2025-06-17T10:09:45.167","IsRefund":false,"RequiredCredit":{"Value":1593.00,"Currency":{"Symbol":"€","Id":4,"Code":"EUR","Description":"Euro"}},"CreatedDateTime":"2025-06-17T10:09:34.997","Status":{"Id":2,"Code":"WaitingForProcessDate","Description":"Waiting for process date"},"TransactionResults":[{"GatewayTransactionId":"1113035925","SplititTransactionId":0,"SplititGatewayTransactionId":"7736aac1-b5ee-4fca-94f9-0ad17902d41f","GatewayResultCode":"AUTH_ONLY","GatewayResultMessage":"AUTH_ONLY","OperationType":{"Id":1,"Code":"Authorize","Description":"Approved"},"GatewayResult":true,"GatewayTransactionDate":"2025-06-17T10:09:34.833Z","IsChargeback":false,"AVSResult":{"Code":null,"Description":null},"CVCResult":{"Code":null,"Description":null}}],"CardDetails":{"CardId":"WdCexD3eTJelpBgvOLomwk95DDYlJfJO9EJ","CardNumber":"************1111","CardExpMonth":null,"CardExpYear":null,"CardBrand":{"Id":2,"Code":"Visa","Description":"VISA"},"CardType":{"Id":1,"Code":"Credit","Description":"CREDIT"},"Bin":"411111","CardHolderFullName":"a**** d***","CardCvv":"[Filtered]","Address":{"AddressLine":"qweqweqw","AddressLine2":null,"City":"portimao","Country":"PT","State":null,"Zip":"8500-112","FullAddressLine":"qweqweqw,portimao,PT"},"Token":null,"FpanLast4Digits":null},"Result":true,"PaymentMethod":"CreditCard","ConsumerFeeAmount":0.0,"OriginalConsumerFeeAmount":{"Value":0.0,"Currency":{"Symbol":"€","Id":4,"Code":"EUR","Description":"Euro"}}},{"InstallmentId":"14688635","InstallmentNumber":2,"Amount":{"Value":796.50,"Currency":{"Symbol":"€","Id":4,"Code":"EUR","Description":"Euro"}},"OriginalAmount":{"Value":796.50,"Currency":{"Symbol":"€","Id":4,"Code":"EUR","Description":"Euro"}},"RefundAmount":{"Value":0.00,"Currency":{"Symbol":"€","Id":4,"Code":"EUR","Description":"Euro"}},"ProcessDateTime":"2025-07-17T10:09:45.167","IsRefund":false,"RequiredCredit":{"Value":796.50,"Currency":{"Symbol":"€","Id":4,"Code":"EUR","Description":"Euro"}},"CreatedDateTime":"2025-06-17T10:09:34.997","Status":{"Id":2,"Code":"WaitingForProcessDate","Description":"Waiting for process date"},"TransactionResults":[],"CardDetails":{"CardId":"WdCexD3eTJelpBgvOLomwk95DDYlJfJO9EJ","CardNumber":"************1111","CardExpMonth":null,"CardExpYear":null,"CardBrand":{"Id":2,"Code":"Visa","Description":"VISA"},"CardType":{"Id":1,"Code":"Credit","Description":"CREDIT"},"Bin":"411111","CardHolderFullName":"a**** d***","CardCvv":"[Filtered]","Address":{"AddressLine":"qweqweqw","AddressLine2":null,"City":"portimao","Country":"PT","State":null,"Zip":"8500-112","FullAddressLine":"qweqweqw,portimao,PT"},"Token":null,"FpanLast4Digits":null},"Result":null,"PaymentMethod":"CreditCard","ConsumerFeeAmount":0.0,"OriginalConsumerFeeAmount":{"Value":0.0,"Currency":{"Symbol":"€","Id":4,"Code":"EUR","Description":"Euro"}}}],"SecureAuthorizations":[{"ProcessingDate":"2025-06-17T10:09:35.07","Amount":{"Value":796.50,"Currency":{"Symbol":"€","Id":4,"Code":"EUR","Description":"Euro"}},"TransactionResults":[{"GatewayTransactionId":"1113036103","SplititTransactionId":0,"SplititGatewayTransactionId":null,"GatewayResultCode":"AUTH_ONLY","GatewayResultMessage":"AUTH_ONLY","OperationType":{"Id":1,"Code":"Authorize","Description":"Approved"},"GatewayResult":true,"GatewayTransactionDate":"2025-06-17T10:09:33.338Z","IsChargeback":false,"AVSResult":{"Code":null,"Description":null},"CVCResult":{"Code":null,"Description":null}}],"CardDetails":{"CardId":"WdCexD3eTJelpBgvOLomwk95DDYlJfJO9EJ","CardNumber":"************1111","CardExpMonth":null,"CardExpYear":null,"CardBrand":{"Id":2,"Code":"Visa","Description":"VISA"},"CardType":{"Id":1,"Code":"Credit","Description":"CREDIT"},"Bin":"411111","CardHolderFullName":"a**** d***","CardCvv":"[Filtered]","Address":{"AddressLine":"qweqweqw","AddressLine2":null,"City":"portimao","Country":"PT","State":null,"Zip":"8500-112","FullAddressLine":"qweqweqw,portimao,PT"},"Token":null,"FpanLast4Digits":null},"Result":true}],"LogoU'+'rl":null,"IsInAutoRetry":false,"PaymentMethod":"CreditCard","AllowCardUpdateOnSplititPortals":true,"OnHoldLastOpenDate":null,"OnHoldLastOpenUserId":null,"InstallmentsScheduleInterval":0,"ExternalPaymentProvider":null,"TerminalApiKey":null,"AmountData":null,"IsPlanWithConsumerFees":false,"NextAuthorization":null,"AnnualPercentageRate":null}}'
)
SIGNATURE_B64 = (
"NC7LOhvRK4JSx0Weibp4gob2L27KSqUg7DHDGaJrRk8PQL+kCCASyvo6f5PjHa0ehJg5eODkWmnOMPpXGVjsvI47A7/L0uxwu/TBWQwo3oLWFYAcSoDwFk6Qbkbh1PrpgI9oRbOtkfLkbVOfdJiubbrFE2kVIgRk7iGdVGZDMh3f17Frqs/57nP0j8qjyFvNmZdO36njKiIbMzVkc6AShCMMOXaI7BP4doUQJIhFQNihsZFC02PpYB5KbKGGiVntEAMyF8//KNyfcgG3ijd8Zjx+gT9/x2/aVZdqTsq9pNWvUApngZVUwPFg7v5dCEhBFf/PsF5LvTqMN8sjxUe/Sw=="
)

def verify_signature(message: bytes, signature_b64: str) -> bool:
"""Verify RSA‑PSS SHA‑256 signature using the public key from the certificate."""

cert = x509.load_pem_x509_certificate(CERT_PEM.encode())
public_key = cert.public_key()
signature = base64.b64decode(signature_b64)

try:
public_key.verify(
signature,
message,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=hashes.SHA256().digest_size, # 32‑byte salt matches .NET default
),
hashes.SHA256(),
)
return True
except Exception:
return False


if __name__ == "__main__":
message = f"{IDEMPOTENCY_KEY};{BODY}".encode()
if verify_signature(message, SIGNATURE_B64):
print("✔ Signature is VALID (RSA‑PSS/SHA‑256)")
else:
print("✖ Signature is INVALID")

Advanced: Parameterized Webhooks

You can request that Splitit support enable parameterized webhooks for you, which will enable you to receive certain plan parameters either directly in your webhook's querystring or in its URL. Available parameters include installment plan number, terminal id, terminal api key, and merchant id.

Querystring Parameters

Request that parameters be returned directly in your webhook's querystring. So, for example, if you request to receive installment plan number, terminal id, terminal api key, and merchant id in your querystring, the following webhook structure will be returned:

https://webhook.site/{__webhook number__}?ipn={__INSTALLMENTPLANNUMBER__}&terminalId={__TERMINALID__}&terminalapikey={__TERMINALAPIKEY__}&merchantId={__MERCHANTID__}**

e.g.:

https://webhook.site/c72da947-52c8-4809-91d1-41f0c85f35bb?ipn=004FANS65QE9LU4D9O90&terminalId=39817&terminalapikey=b127c9a4-4c22-4791-97c4-c9f8da665a60&merchantId=91157

URL Parameters

Request that parameters be returned in the URLs of your webhooks. So, for example, if you request to receive installment plan number, terminal id, terminal api key, and merchant id in your URLs, the following webhook structure will be returned:

https://webhook.site/{__webhook number__}/{__INSTALLMENTPLANNUMBER__}/{__TERMINALID__}/{__TERMINALAPIKEY__}/{__MERCHANTID__}/

e.g.:

https://webhook.site/c72da947-53c8-4809-90d1-41f0c85f35bb/54443224184238313683/30817/b628b9a4-4c21-4691-97c4-c9f8da665a60/01657/