Download OpenAPI specification:Download
Hi 👋,
Before you skip straight to the code please take a sip of your brew and read this block.
HUP is a platform that connects payment methods to Payment Service Providers (PSPs) and enables offering proprietary payment methods within the Buy Now Pay Later (BNPL) ecosystem.
If you have any questions regarding the integration with our Api, please contact one of the following:
Development:
Merchant/Shop/Customer:
Before starting integration with HUP, check if all legal documents (KYC checks) and merchant contracting are covered in your onboarding!
sequenceDiagram participant Customer participant Merchant participant PSP participant Hup participant BNPL
Customer->>Merchant: Start checkout
Merchant->>PSP: Create order with details
PSP->>Hup: Forward transaction request
Hup->>BNPL: [POST] Start transaction
BNPL-->>Hup: Payment screen URL
Hup-->>PSP: Pass back payment screen URL
PSP-->>Merchant: Redirect customer
Merchant-->>Customer: Show BNPL payment screen
Customer->>BNPL: Authenticate & pay first installment
BNPL-->>Hup: Payment status update
Hup-->>PSP: Payment status
PSP-->>Merchant: Success / Failure
Merchant-->>Customer: Show order result
Starts an in3 transaction.
Note: At in3 we always prefer that you provide array of invoiceLines in your Api call, if it`s not possible to provide the invoiceLines, we can work around it.
Please contact us on: product@payin3.nl
required | object (CustomerInfo) |
object (InvoiceInfo) | |
required | Address (object) Address where the products will be shipped |
(Address (object or null)) Address where the invoice will be sent, same as shipping address when null | |
Array of objects (InvoiceLine) | |
required | object (ApiOptions) |
(Psper (object or null)) PSPer only! Used by PSPers to facilitate in3 transactions for connected shops |
{- "customerInfo": {
- "id": "012afad1-6a66-4177-9447-798d5de2f16d",
- "firstName": "Nick",
- "initials": "N.K.G.",
- "lastName": "Vliet",
- "dateOfBirth": "1998-07-17",
- "phoneNumber": "+31651267472",
- "email": "debtor@mail.scenius.nl",
- "fax": null,
- "isBusiness": false,
- "businessName": "Hogeschaar B.V.",
- "cocNumber": "70528500"
}, - "invoiceInfo": {
- "invoiceAmount": 42656,
- "vatTotal": 8957,
- "invoiceReference": "IN3242",
- "invoiceDescription": "API Test Order",
- "invoiceDate": "2020-01-01",
- "invoiceUrl": null
}, - "shippingAddress": {
- "addressedTo": "Scenius",
- "street": "Collse Heide",
- "city": "Nuenen",
- "houseNumber": "50",
- "houseNumberSuffix": "C",
- "postalCode": "5674 VN",
- "region": "Noord-Brabant",
- "countryCode": "NL"
}, - "invoiceAddress": {
- "addressedTo": "Scenius",
- "street": "Collse Heide",
- "city": "Nuenen",
- "houseNumber": "50",
- "houseNumberSuffix": "C",
- "postalCode": "5674 VN",
- "region": "Noord-Brabant",
- "countryCode": "NL"
}, - "invoiceLines": [
- {
- "code": null,
- "type": "product",
- "description": "Ergonomic Concrete Table",
- "productCategory": "Tables",
- "quantity": 2,
- "unitPrice": 21328,
- "quantityDescription": "pieces",
- "price": 42656,
- "vatPercentage": 21,
- "vatAmount": 8957,
- "expectedDeliveryDate": "2021-01-01"
}
], - "apiOptions": {
- "expiresOn": "2030-10-08T09:10:35Z",
- "interfaceLocaleOverride": "nl",
- "route": "in3",
- "isTest": true
}, - "pspOptions": {
- "pspTransactionIdentifier": "0f9effab-6b7e-4315-b0e8-f9dcbaa8033c",
- "merchantInfo": {
- "internalMerchantId": "80041fe3-266b-4006-9579-03bd8ced0b04",
- "merchantName": "DemoMerchant Financial Asset Holding G.M.B.H.",
- "method": "IN3GRNT",
- "legalAddress": {
- "street": "Collse Heide",
- "city": "Nuenen",
- "houseNumber": "50",
- "houseNumberSuffix": "C",
- "postalCode": "5674VN",
- "region": "Noord-Brabant",
- "countryCode": "NL"
}, - "cocNumber": "70528500",
- "vatNumber": "NL999999999B99",
- "iban": "NL63RABO7608092459",
- "ascription": "DemoMerchant Financial Asset Holding G.M.B.H.",
- "authorizedContact": {
- "firstNames": "Henk",
- "lastName": "Jansen",
- "email": "h.jansen@payin3.nl",
- "phoneNumber": "+31651267472"
}, - "financialContact": {
- "firstNames": "Henk",
- "lastName": "Jansen",
- "email": "h.jansen@payin3.nl",
- "phoneNumber": "+31651267472"
}, - "marketingContact": {
- "firstNames": "Henk",
- "lastName": "Jansen",
- "email": "h.jansen@payin3.nl",
- "phoneNumber": "+31651267472"
}, - "supportContact": {
- "firstNames": "Henk",
- "lastName": "Jansen",
- "email": "h.jansen@payin3.nl",
- "phoneNumber": "+31651267472"
}, - "technicalContact": {
- "firstNames": "Henk",
- "lastName": "Jansen",
- "email": "h.jansen@payin3.nl",
- "phoneNumber": "+31651267472"
}, - "variableFee": 3.4,
- "fixedFee": 949.99,
- "merchantPayoutDate": 7,
- "pspPayoutDate": 7,
- "thirdPartyReseller": "Scenius"
}, - "shopInfo": {
- "internalShopId": "1529251e-2d0d-4532-86c8-7b2c711fddc7",
- "name": "DemoMerchant",
- "shopAddress": {
- "street": "Collse Heide",
- "city": "Nuenen",
- "houseNumber": "50",
- "houseNumberSuffix": "C",
- "postalCode": "5674VN",
- "region": "Noord-Brabant",
- "countryCode": "NL"
}, - "categories": [
- "Televisions"
], - "customerSupportPhone": "+31403690149",
- "customerSupportEmail": "support@payin3.nl",
- "platform": "Magento2",
- "captureMethod": null,
- "expectedTraffic": 1500,
- "fixedFee": 1.5,
- "variableFee": 1.5,
- "mccCode": "1234",
- "mccDescription": "Mollie"
}
}
}{- "transactionIdentifier": "0af7c4b50f894420bc1ec565974bbf64fWBHL2tpvbhs3WQoN2MlPlR",
}Gets the status of an in3 transaction.
Status descriptions:
The following state transitions are possible. Note that only the flow that ends in FirstTermPaid is considered a succesful flow. In all other cases, the payment did not go through and no goods should be shipped by the merchant.

| transactionIdentifier required | string[a-zA-Z0-9\-]+ /api/transaction/{transactionIdentifier} (Returned by POST /api/transaction) |
{- "status": "FirstTermPaid"
}List all credits/restitutions/refunds for the specified transaction.
| transactionIdentifier required | string[a-zA-Z0-9\-]+ /api/transaction/{transactionIdentifier} (Returned by POST /api/transaction) |
[- {
- "RefundIdentifier": "15f69ac2-4c83-4171-b17c-3bc7773bb8df",
- "requestDate": "2022-02-23T16:46:34.3373917+01:00",
- "description": "Refund store",
- "amount": 23456,
- "fundsTranferConfirmedOn": "2022-02-23T16:46:34.3373917+01:00"
}
]Creates a credit/restitution/refund for the specified order. Multiple refunds are allowed, but the sum of all refunds may not exceed the original invoice amount.
| transactionIdentifier required | string[a-zA-Z0-9\-]+ /api/transaction/{transactionIdentifier} (Returned by POST /api/transaction) |
| description required | string or null <= 256 characters The description of the refund. E.g. return number |
| amount required | number >= 1 The amount that should be refunded in cents. Cannot be higher than the original invoice amount |
{- "description": "2f5c43a5-570b-4206-b5fd-882ea51eb8c3",
- "amount": 24234
}{- "identifier": "2Upb15Afx364f064d26Js26F80b73Q4d27b3cxy5fmEbCdbl"
}Total captured amount across all capture requests must not exceed the originally authorized transaction amount.
Multiple partial captures are allowed.
Transactions without capture after a defined window (e.g., 30 days) may expire automatically.
| transactionIdentifier required | string[a-zA-Z0-9\-]+ /api/transaction/{transactionIdentifier} (Returned by POST /api/transaction) |
{- "transactionIdentifier": "0af7c4b50f894420bc1ec565974bbf64fWBHL2tpvbhs3WQoN2MlPlR",
- "totalAuthorized": 5000,
- "totalCaptured": 5000,
- "remaining": 5000,
- "captures": [
- {
- "amount": 5000,
- "currency": "EUR",
- "captureReference": "SHIPMENT-001",
- "timestamp": "2025-04-11T09:10:35Z"
}
]
}Total captured amount across all capture requests must not exceed the originally authorized transaction amount.
Multiple partial captures are allowed.
Transactions without capture after a defined window (e.g., 30 days) may expire automatically.
| transactionIdentifier required | string[a-zA-Z0-9\-]+ /api/transaction/{transactionIdentifier} (Returned by POST /api/transaction) |
| amount required | number >= 1 The amount in cents that was affected in this capture event |
| currency required | string <= 3 characters The currency in ISO 4217 |
| captureReference required | string <= 256 characters The reference for this capture event |
{- "amount": 5000,
- "currency": "EUR",
- "captureReference": "SHIPMENT-001"
}{- "transactionIdentifier": "0af7c4b50f894420bc1ec565974bbf64fWBHL2tpvbhs3WQoN2MlPlR",
- "capturedAmount": 5000,
- "currency": "EUR",
- "captureReference": "SHIPMENT-001",
- "status": null,
- "remaining": 5000,
- "timestamp": "2025-04-11T09:10:35Z"
}Extends the capture window for transaction.
| transactionIdentifier required | string[a-zA-Z0-9\-]+ /api/transaction/{transactionIdentifier} (Returned by POST /api/transaction) |
| newExpiryDate required | string >= 1 The new deadline date in ISO 8601 in UTC time |
| reason required | string <= 1024 characters The reason for extending the capture window |
{- "newExpiryDate": "2025-04-11T09:10:35Z",
- "reason": "Supply Issues"
}{- "transactionIdentifier": "0af7c4b50f894420bc1ec565974bbf64fWBHL2tpvbhs3WQoN2MlPlR",
- "oldExpiryDate": "2025-04-11T09:10:35Z",
- "newExpiryDate": "2025-04-14T09:10:35Z"
}Get informed when something relevant changes. Here you can setup which URL we should inform. All webhooks only inform you of the changed ID's so that you can fetch the latest status yourself completing the triangle.
Confirming HMAC on the receiving side of the webhook is as following:
"hmac_date", and seperate them with a semicolon. {"key":"value"};1646147678/// <summary>
/// Verifies HMAC from webhook
/// </summary>
/// <param name="hmac">Hmac header</param>
/// <param name="hmacDate">Hmac_date header</param>
/// <param name="jsonBody">The full response body</param>
/// <param name="signingKey">The signing key that was transmitted on the creation of the webhook.</param>
/// <returns></returns>
public bool VerifyHmac(string hmac, long hmacDate, string jsonBody, string signingKey)
{
if (DateTimeOffset.FromUnixTimeSeconds(hmacDate) > DateTimeOffset.Now.AddMinutes(15))
{
// Timestamp in HMAC is too old, or modified.
return false;
};
var payload = $"{jsonBody};{hmacDate}";
var signingKeyDecoded = Convert.FromBase64String(signingKey);
var signature = string.Empty;
using (var hmacsha512 = new HMACSHA512(signingKeyDecoded))
{
var stream = new MemoryStream(Encoding.UTF8.GetBytes(payload));
foreach (var b in hmacsha512.ComputeHash(stream))
{
signature = signature + $"{b:x2}";
}
}
return hmac == signature;
}
GET /api/v3/webhook HTTP/1.1 Host: webhook.partner.eu x-hmac: b8b6fa39866b125555772e955107a641522a610091dcdc734c7a8d1ea1f92563f060e8ebb9263f7b5a3173191594320b6d50c7cc19d76be42e2df3ed1d3e4c20 x-hmac-date: 1656418731 {"test":"test"} Signing_Key: PRHVXZL739Hu8kVaZyxzMUGGMe/w12Meuy9aRQo7BFxf7oYoepN/GsY3ZmCotsuJtoxSfYKpEEjsyvrAUWDyzA==
[- {
- "id": "49e2576a-8cab-4ded-99fc-36feb779e69e",
- "name": "Failover event ingest - in3 onboarding",
- "expectedResponseMessage": "ACK",
- "expectedStatusCode": 200,
- "eventType": "OnboardingState",
- "retryPolicy": "Retry"
}
]| name required | string <= 128 characters The name of the webhook |
| url required | string <= 2048 characters The URL in3 will call |
| eventType required | string Enum: "TransactionState" "OnboardingState" "FraudState" "TransactionCaptureState" The type of events this webhook should receive |
| expectedResponseMessage | string or null <= 25 characters Default: null The response body we should expect to consider the callback successful. Empty is always OK |
| expectedStatusCode | number or null Default: 200 The response body we should expect to consider the callback successful. |
| retryPolicy | string Default: "NoRetry" Enum: "NoRetry" "Retry" With the retry policy we will retry the call a few more times with increasing interval |
{- "name": "Failover event ingest - in3 onboarding",
- "eventType": "OnboardingState",
- "expectedResponseMessage": "ACK",
- "expectedStatusCode": 200,
- "retryPolicy": "Retry"
}{- "id": "49e2576a-8cab-4ded-99fc-36feb779e69e",
- "name": "Failover event ingest - in3 onboarding",
- "eventType": "OnboardingState",
- "expectedResponseMessage": "ACK",
- "expectedStatusCode": 200,
- "retryPolicy": "Retry",
- "signingKey": "FX0369C0DN0402H3DB0SIJSLW0E2HAQ4"
}{- "id": 294241568,
- "event": "OnboardingState",
- "entityId": "49e2576a-8cab-4ded-99fc-36feb779e69e"
}| webhookId required | string[a-zA-Z0-9\-]+ /api/webhook/{webhookId} |
DELETE /api/v3/webhook/521a61c8-ba9d-4c16-95f3-08d9c3024e15 HTTP/1.1 Host: webhook.partner.eu x-hmac: b8b6fa39866b125555772e955107a641522a610091dcdc734c7a8d1ea1f92563f060e8ebb9263f7b5a3173191594320b6d50c7cc19d76be42e2df3ed1d3e4c20 x-hmac-date: 1656418731 {"test":"test"} Signing_Key: PRHVXZL739Hu8kVaZyxzMUGGMe/w12Meuy9aRQo7BFxf7oYoepN/GsY3ZmCotsuJtoxSfYKpEEjsyvrAUWDyzA==