Trusted payments
This guide details how to implement Digiteal's Trusted Payment (Escrow) system. This flow is built for integrators and platforms that want to utilize a regulated, neutral escrow system to secure funds between buyers and sellers. This significantly reduces your administrative overhead, manual reconciliation efforts, and compliance liability.
🎯 The Trusted Payment Workflow
The Scenario: You run a platform or software that facilitates financial transactions between two or more parties. The Solution: Instead of receiving funds into your own accounts, your system opens an automated "Escrow Container" for the transaction. Clients pay directly into this secure transit account. Your platform can dynamically adjust payment splits and trigger partial or full payouts to the seller, while retaining full control over when the funds are ultimately released.
🛠 Phase 1: Onboarding Users (KYC)
Before a seller or creditor can receive payouts, they must be registered and verified within Digiteal’s ecosystem.
- Endpoints: Use POST /api/v1/kyc/company (for registered businesses)
- The Process: Pre-register the company via the API so they can legally receive funds.
- Low Volume: If the company expects to receive
< €3,000annually, the standard API pre-registration is usually sufficient to begin. - High Volume: If they exceed compliance thresholds, you must prompt them to upload identification documents using POST /api/v1/kyc/document
🧳 Phase 2: Creating the Escrow "Wallet" & Setting Permissions
For each new transaction, project, or billing cycle, you must create a confirmation-based transfer. This acts as the legal escrow container.
- Endpoint: POST /api/v1/transfers/confirmation-based
Strategy:
- Capacity: Set the
amountInCentswithin thetransferPaymentsarray to an arbitrarily high number. This ensures the escrow container can accommodate the total expected volume without hitting a restrictive ceiling. - The
decideFlag (Crucial): Configure thedecideflag within theactorsarray to enforce strict escrow rules. For example, the integrator (_3RD_PARTY) and the buyer (BUYER) should havedecide: trueso they can authorize the release, while the seller (SELLER) must be set todecide: falseso they cannot release funds to themselves prematurely.
Example Payload:
{
"projectName": "Project - Order #1234",
"transferPayments": [
{
"amountInCents": 15000,
"communication": "Payout for Order #1234",
"creditorEmail": "[email protected]",
"reference": "PAY-REF-01"
}
],
"actors": [
{
"type": "BUYER",
"email": "[email protected]",
"decide": true
},
{
"type": "_3RD_PARTY",
"vatNumber": "BE0123456789",
"decide": true
},
{
"type": "SELLER",
"email": "[email protected]",
"decide": false
}
]
}
Note: Save the
transferID(UUID) returned in the200 OKresponse. You will need it for all subsequent steps.
💳 Phase 3: Collecting Funds (Pay-Ins) & Generating Payment Links
When a transaction is initiated, you need to route the client's money into the escrow. To prevent malicious users from tampering with parameters (like lowering the payment amount), you must secure the payment links.
Approach A: Construct a payment link (GET method)
Construct the Raw Execution URL
Build the raw URL targeting the /api/v1/pay-button/execute endpoint, injecting the trustedPaymentUUID from Phase 2.
https://app.digiteal.eu/api/v1/payment-request/pay-button/execute?trustedPaymentUUID=e529f8b4-790f-11e7-b5a5-be2e44b06b52&amountInCents=15000&qrCode=true&confirmationURL=https://yourplatform.com/payment/success&errorURL=https://yourplatform.com/payment/error
(Setting qrCode=true renders a scannable Bancontact/Payconiq code for in-person or "Soft POS" scenarios).
Secure it with the Short Link API
Pass the raw URL to the POST /api/v1/shortLink endpoint to lock the parameters in place.
Example Payload:
{
"longURL": "https://app.digiteal.eu/api/v1/payment-request/pay-button/execute?trustedPaymentUUID=e529f8b4-790f-11e7-b5a5-be2e44b06b52&amountInCents=15000&qrCode=true&confirmationURL=https://yourplatform.com/payment/success&errorURL=https://yourplatform.com/payment/error"
}
Response:
{
"shortURL": "https://app.digiteal.eu/p/abcde"
}
Action: Present this shortURL to the customer (via email, SMS, or displayed as a QR code).
Approach B: Trusted Payment Link Generation (POST - Recommended)
Endpoint: POST [/api/v1/payment-request/trustedPayment](createtrustedpaymentcollectionrequest)
This endpoint provides a dedicated Trusted Payment specific counterpart to standard payment requests. Instead of passing standard merchant details, you link the payment directly to the pre-created Trusted Payment transfer IDs or creditor references. This is the recommended server-side approach for marketplaces wanting to securely generate payment links explicitly tied to their escrow containers.
Base Parameters
Send a POST request with the following JSON body parameters. To identify which trusted payment(s) you are collecting funds for, you must use one of the identifier methods (transferId, transferIds, creditorReference, creditorReferences, or contributions).
Note: If you provide multiple identification types, they are processed in order of priority: contributions > transferIds > transferId > creditorReferences > creditorReference.
| Parameter | Type | Required | Description |
|---|---|---|---|
amountInCents | integer | No | The amount to charge in cents (e.g., 1234 for 12.34). If not provided for a confirmation-based trusted payment, the total remaining amount of the trusted payment will be requested automatically. |
confirmationURL | string | Yes | The URL where the user is redirected after a successful payment (Max 255 chars). |
errorURL | string | Yes | The URL where the user is redirected if an error occurs during the payment (Max 255 chars). |
cancelURL | string | No | The URL where the user is redirected if they cancel the payment. If omitted, the user is sent to the errorURL. |
language | string | No | The language of the checkout interface. Accepted values are NL, FR, or EN. |
Trusted Payment Identifiers (Choose One)
| Parameter | Type | Description |
|---|---|---|
transferId | string (uuid) | The Digiteal UUID of a single trusted payment transfer. |
transferIds | array of uuids | An array of Digiteal UUIDs for multiple trusted payment transfers you want to collect at once. |
creditorReference | string | The single creditor reference associated with the trusted payment. |
creditorReferences | array of strings | An array of creditor references for multiple trusted payments. |
contributions | array of objects | Specific contributions to the trusted payments |
Example Request
Because the payment URLs are returned in the headers instead of the body, be sure your client is configured to read the HTTP response headers.
curl -i -X POST [https://test.digiteal.eu/api/v1/payment-request/trustedPayment](https://test.digiteal.eu/api/v1/payment-request/trustedPayment) \
-H "Authorization: Basic YOUR_BASE64_CREDENTIALS" \
-H "Content-Type: application/json" \
-d '{
"transferId": "48e382de-1740-40e6-9902-b3bd3ead8e62",
"amountInCents": 15000,
"confirmationURL": "[https://yourmarketplace.com/checkout/success](https://yourmarketplace.com/checkout/success)",
"errorURL": "[https://yourmarketplace.com/checkout/error](https://yourmarketplace.com/checkout/error)",
"cancelURL": "[https://yourmarketplace.com/checkout/cancel](https://yourmarketplace.com/checkout/cancel)",
"language": "EN"
}'📡 Phase 4: Event Monitoring (The Complete Webhook Lifecycle)
To automate the workflow without relying on frontend redirects, your backend server must listen to Digiteal's webhooks.
1. The Buyer Pay-In Flow (Payment Webhooks)
These events indicate what is happening when the buyer interacts with the payment link. 📖 Learn more: Read the full Payment Webhooks guide
PAYMENT_INITIATED_V2: Triggered when the buyer officially initiates the payment (e.g., authenticates their banking app).PAYMENT_INITIATION_ERROR_V2: Triggered if the payment fails on the buyer's side. Integrator Action: Prompt the buyer to try another payment method.PAYMENT_RECEIVED_IN_TRANSIT: Triggered when the money physically arrives in Digiteal's secure transit account.
2. The Escrow Lifecycle (Transfer Webhooks)
These core events dictate your business logic and indicate when funds are secured or released. 📖 Learn more: Read the full Trusted Payment Webhooks guide
TRANSFER_CREATED: A trusted payment (escrow container) has been created. Integrator Action: Link thetransferIdto your internal transaction ID.TRANSFER_PAYMENT_RECEIVED: A payment awaiting confirmation has been received into the escrow. Integrator Action: This is the green light. The funds are 100% secured and locked; the service or product delivery can commence.TRANSFER_PAYMENT_STARTED: A trusted payment execution has started. The money transfer order to the creditor will soon be executed.TRANSFER_PAYMENT_COMPLETED: The transfer has been completed successfully. Integrator Action: The funds have settled in the respective bank accounts. Mark the transaction as complete.
If a transaction is disputed or canceled after the payout, you can track the lifecycle of the money flowing back to the buyer.
REIMBURSEMENT_RECEIVED_FROM_CREDITOR: Confirmation that Digiteal received the funds back from a specific creditor (sent per creditor involved in the refund). The payload contains the payment info and the transfer reference.TRANSFER_REIMBURSEMENT_STARTED: Triggered once Digiteal has successfully retrieved all funds from all requested creditors and is about to send the full amount as a unique payment back to the debtor.TRANSFER_REIMBURSEMENT_COMPLETED: The debtor has successfully received the refund payment from Digiteal. This officially ends the refund process.
✂️ Phase 5: Managing, Splitting, and Releasing Funds
The integrator dictates when and how the secured funds are disbursed. Because of the decide flag set in Phase 2, the execution endpoints will only work if called by authorized actors.
5a. Update the Split (Dynamic Fees/Commissions)
- Endpoint: POST /api/v1/transfers/confirmation-based/uuid/payments
- Usage: Modify the escrow parameters dynamically. Update the
transferPaymentsarray to designate the finalcreditorIBANand optionally deduct an integrator fee by targeting thereferenceestablished in Phase 2.
Example Payload:
{
"updates": [
{
"reference": "PAY-REF-01",
"amountInCents": 12000,
"communication": "Final payout minus service fee"
},
{
"reference": "PAY-REF-01",
"subReference": "FEE-01",
"amountInCents": 3000,
"communication": "Integrator Fee Job #1234",
"creditorIBAN": "BE12345678901234"
}
]
}
5b. Execute the Payout
Once conditions are met (e.g., the buyer confirms receipt), your backend makes this call to release the money.
- Endpoint: POST /api/v1/transfers/execute
Example Payload:
{
"transferID": "e529f8b4-790f-11e7-b5a5-be2e44b06b52",
"validate": true,
"comment": "Transaction verified. Releasing funds."
}
Note: Setting
validate: trueperforms a full release of all secured funds and closes the escrow container. For ongoing, long-living escrows, usePOST /api/v1/transfers/confirmation-based/{uuid}/partialExecutioninstead.
⏪ Phase 6: Handling Disputes and Refunds
If a transaction is canceled or a dispute arises after an execution has already taken place, you can request to pull the funds back from the seller(s) and refund the buyer.
- Endpoint: POST /api/v1/payments/paymentId/transfers/transferId/refund
- How it Works: Digiteal retrieves the funds from the creditor(s) via Direct Debit (SDD). Once all requested funds are secured, Digiteal issues a refund to the debtor via Bank Transfer (SCT).
- Multiple Transfers: If the original payment funded multiple transfers, you must make a separate API call for each specific
transferId. - Response: Look in the headers of the
200 OKresponse for the UUID of the refund payment to track its status.
6a. Full Refunds
A full refund is executed by leaving the list of contributions empty. Digiteal will retrieve the full amount of all the payments made to all creditors associated with the transfer.
Example Payload (Full Refund):
{
"communication": "Refund from payment cart-1234 of 15/05/2023"
}
6b. Partial Refunds
To request a partial refund, you use the contributions attribute (refundContributions). Each contribution defines the specific amount to be retrieved from a specific creditor linked to the transfer. Only the contributions defined in the request are refunded.
- Rules: The amount of each contribution must be positive and must not exceed the amount that was originally paid to that specific creditor.
Example Payload (Partial Refund):
{
"communication": "Refund from payment cart-1234 of 15/05/2023",
"refundContributions": [
{
"contributorIban": "ES0720951914701193632422",
"amountInCents": "9250",
"currency": "EUR",
"communication": "Refund from payment cart-1234 of 15/05/2023",
"reference": "REFERENCE_ID1"
},
{
"contributorIban": "ES1401827984057893687272",
"amountInCents": "750",
"currency": "EUR",
"communication": "Refund from payment cart-1234 of 15/05/2023",
"reference": "REFERENCE_ID2"
}
]
}
Updated 3 days ago
