Async Payment
sequenceDiagram
Browser->>+Website: Request to initiate payment
Website->>+Api: Create Async Payment
Api->>+Website: Response with url
Website->>+Browser: Iframe or redirect to url
Browser->>+PayLolly: Redirect to paylolly
PayLolly->>+PayLolly: Process transaction
PayLolly->>+Browser: Redirect to Website
Browser->>+Website: Back from payment
Api->>+Website: Webhook (optional)
Use Cases
Async Payment - Single one-shot payment
Use Payment/CreateAsyncPayment call
- Populate merchantId
- Optionally populate accountid if you want to force a particular account
- Populate Currency ex EUR
- Populate amount ex 1.00
- Create a merchantRef - must be unique - suggest Guid
- Enter cardholder details
- Enter card details in cardData
- Populate AuthorisationType depending on your use case
- Preauth - Auth
- Preauth and Capture - AuthCapture
- Recurrence - OneTime
- WebHooks - suggest population of completed and approved webhooks to receive server-to-server call when payment completed
- Initiation - set to CIT (the only value accepted on async payments:
MITandMOTOare rejected withVAL13) - ReturnUrl - enter a valid url to redirect cardholder at the end of the payment
- ThreeDSConfig - see ThreeDSConfig - default values apply if omitted
- validUntil - enter a valid until date/time - suggest 20 minutes
The above will create a single one-shot payment request
request:
{
"returnUrl": "https://portal.dev.paylolly.app/VirtualTerminal/Async/Return",
"validUntil": "2022-11-04T11:15:54.8200623Z",
"merchantId": "dbdab964-82ee-4b09-a26b-68403c31afa7",
"currency": "EUR",
"amount": 100.0,
"merchantRef": "2425363c-5541-4c37-a698-77447650610d",
"cardHolder": {
"email": "test@test.com",
"name": "test user"
},
"cardData": {
"cardNo": "4000000000000002",
"expiryYear": "22",
"expiryMonth": "12",
"cvc": "123",
"expiryYYMM": "2212"
},
"authorisationType": "AuthCapture"
}
response:
{
"redirectUrl": "https://api.dev.paylolly.app/payment/async/ed9d773b-f27b-4286-8525-cbb9293d7604/Index",
"paymentId": "ed9d773b-f27b-4286-8525-cbb9293d7604",
"merchantId": "dbdab964-82ee-4b09-a26b-68403c31afa7",
"accountId": "81de44cb-4b70-4207-9f5e-54355491a5cc",
"currency": "EUR",
"amount": 100,
"cardData": {
"maskedPAN": "400000*0002",
"expiryYYMM": "2212",
"token": "830DAE88123E8DD3DEF9658E846F97C2"
},
"threeDSData": null,
"result": {
"status": "Async",
"processorId": "35cdb967-a12a-4bae-9dfd-9617a8f8abae",
"message": "redirect to async",
"authCode": null,
"traceId": null,
"standardHostCode": null,
"mastercardMacCode": null
},
"merchantRef": "2425363c-5541-4c37-a698-77447650610e"
}
Async Payment - one-shot payment with previous details (fixed) - repeated payment CIT
Use Payment/CreateAsyncPayment call
Populate merchantId
Optionally populate accountid if you want to force a particular account
Populate Currency ex EUR
Populate amount ex 1.00
Create a merchantRef - must be unique - suggest Guid
Enter cardholder details if known
populate tokenData with previous payment Token
Populate AuthorisationType depending on your use case
- Preauth - Auth
- Preauth and Capture - AuthCapture
Recurrence - OneTime
WebHooks - suggest population of completed and approved webhooks to receive server-to-server call when payment completed
Initiation - set to CIT (the only value accepted on async payments:
MITandMOTOare rejected withVAL13)ReturnUrl - enter a valid url to redirect cardholder at the end of the payment
ThreeDSConfig - see ThreeDSConfig - default values apply if omitted
validUntil - enter a valid until date/time - suggest 20 minutes
The above will create a single one-shot payment request
request:
{
"returnUrl": "https://portal.dev.paylolly.app/VirtualTerminal/Async/Return",
"validUntil": "2022-11-04T11:15:54.8200623Z",
"merchantId": "dbdab964-82ee-4b09-a26b-68403c31afa7",
"currency": "EUR",
"amount": 100.0,
"merchantRef": "2425363c-5541-4c37-a698-77447650610b",
"cardHolder": {
"email": "test@test.com",
"name": "test user"
},
"tokenData": {
"token": "830DAE88123E8DD3DEF9658E846F97C2"
},
"cardData":{
"cvc":"123"
},
"authorisationType": "AuthCapture"
}
response:
{
"redirectUrl": "https://api.dev.paylolly.app/payment/async/469a8e0f-8633-4f67-bb2b-cc08722edc83/Index",
"paymentId": "469a8e0f-8633-4f67-bb2b-cc08722edc83",
"merchantId": "dbdab964-82ee-4b09-a26b-68403c31afa7",
"accountId": "81de44cb-4b70-4207-9f5e-54355491a5cc",
"currency": "EUR",
"amount": 100,
"cardData": {
"maskedPAN": "400000*0002",
"expiryYYMM": "2212",
"token": "830DAE88123E8DD3DEF9658E846F97C2"
},
"threeDSData": null,
"result": {
"status": "Async",
"processorId": "bec048de-d9f9-48f0-82b2-94833f9698e4",
"message": "redirect to async",
"authCode": null,
"traceId": null,
"standardHostCode": null,
"mastercardMacCode": null
},
"merchantRef": "2425363c-5541-4c37-a698-77447650610b"
}
Tip
See Payment Actions for further actions possible on completed async payment
Async Payment - register a card with an agreement
Tip
For a subscription or instalments (fixed amount and interval) use recurrence Scheduled and agreement.schedule instead of OneClick, see Agreements.
Use this to save the card for later payments (merchant initiated payments, one-click) and record what the cardholder agreed to, when you show the consent on your own page. (On the hosted page PayLolly shows and records the consent for you, see Hosted Payment.) The concepts and all channels are in Agreements.
Use Payment/CreateAsyncPayment as for a one-shot payment, but:
recurrence: OneClick (the registering payment)initiation: CITcardHolder.reference: your id for the customer (mandatory, 1 to 64 characters)agreement: what was agreeddescription: what the card may be used for (optional on async)agreementRef,maxAmount,expiresAt: optionalconsent: mandatory -textVersion(the version of the consent text you showed),timestamp(when the cardholder agreed, UTC, not in the future), optionallyip(default: the browser address PayLolly sees during 3D Secure) andevidenceRef(your own record of the consent, for disputes)
- the merchant must be enabled for agreements (
AGR09)
The consent is your assertion: PayLolly records it as attested by you. Show the cardholder the exact text you version, and keep your own record.
request:
{
"returnUrl": "https://portal.dev.paylolly.app/VirtualTerminal/Async/Return",
"validUntil": "2026-11-04T11:15:54.8200623Z",
"merchantId": "dbdab964-82ee-4b09-a26b-68403c31afa7",
"currency": "EUR",
"amount": 25.0,
"merchantRef": "2425363c-5541-4c37-a698-77447650610c",
"cardHolder": {
"reference": "CUST-1",
"email": "test@test.com",
"name": "test user"
},
"cardData": {
"cardNo": "4000000000000002",
"expiryYYMM": "3012",
"cvc": "123"
},
"authorisationType": "AuthCapture",
"recurrence": "OneClick",
"initiation": "CIT",
"agreement": {
"agreementRef": "TOPUP-1",
"description": "Wallet top-ups",
"maxAmount": 100,
"consent": {
"textVersion": "v3",
"timestamp": "2026-10-16T09:00:00Z",
"evidenceRef": "consent-2026-10-16-4711"
}
}
}
response (the payment is pending until the cardholder has been through 3D Secure, so there is no agreement yet):
{
"redirectUrl": "https://api.dev.paylolly.app/payment/async/469a8e0f-8633-4f67-bb2b-cc08722edc84/Index",
"paymentId": "469a8e0f-8633-4f67-bb2b-cc08722edc84",
"merchantId": "dbdab964-82ee-4b09-a26b-68403c31afa7",
"currency": "EUR",
"amount": 25,
"merchantRef": "2425363c-5541-4c37-a698-77447650610c"
}
Send the cardholder to redirectUrl. PayLolly runs 3D Secure, which always asks the cardholder to authenticate (a mandated challenge, indicator 04) on a registering payment. After approval the agreement is registered and the outcome is in Payment/GetPaymentStatus and in your completed and approved webhooks:
{
"paymentId": "469a8e0f-8633-4f67-bb2b-cc08722edc84",
"result": { "status": "Approved" },
"cardData": { "maskedPAN": "400000*0002", "token": "08524FF1F8BE79B7EA0CE19204E81BF2" },
"agreement": {
"agreementId": "0198ab5c-6f37-7a02-9d7e-3a5e2c1f4b10",
"status": "Created",
"agreementRef": "TOPUP-1",
"consentStatus": "Recorded"
}
}
Store the token and the agreementId for the customer. Later payments quote them, see Payment Actions. Declined payments register nothing (NotCreated / PaymentNotApproved). The same customer, card and agreementRef again updates the same agreement. See Webhooks for the outcomes.