A PaymentRequest defines who is paying, who is receiving, the amount and how the payment should be processed.
It is used in both the authorisation step (POST /payment-auth-requests) and the execution step (POST /payments). The object structure is consistent across countries and payment types. However, required fields vary by country, standard and individual institution.
If you are using Hosted Pages, you still provide payee details and payment parameters in the request that creates the Hosted session. Hosted then handles bank selection, payer authorisation, and SCA on the user’s side. The field details below apply to both integration approaches.
A UK domestic payment needs a sort code and account number. A German SEPA payment needs an IBAN. Some European banks require payer details, others do not.
PaymentRequest structure
| Field | Type | Description |
|---|
type | string | Payment type (DOMESTIC_PAYMENT, INTERNATIONAL_PAYMENT, etc.) |
paymentIdempotencyId | string | Your unique reference. Prevents duplicates. |
amount.amount | number | Payment amount |
amount.currency | string | Three-letter currency code (GBP, EUR) |
reference | string | Payment description visible on bank statements |
payee.name | string | Recipient name |
payee.accountIdentifications[] | array | Recipient account details (SORT_CODE, IBAN, etc.) |
payee.address | object | Recipient address (sometimes required) |
payer.name | string | Sender name (sometimes required) |
payer.accountIdentifications[] | array | Sender account details (sometimes required) |
payer.address | object | Sender address (sometimes required) |
Payment types
| Your Scenario | Payment Type | Key Consideration |
|---|
| UK to UK, standard speed | Single Domestic Payment | Uses Faster Payments |
| EU to EU (same or different country), euros | Single Domestic Payment | Routed via SEPA |
| EU to EU, euros, instant | Single Domestic Instant Payment | SEPA Instant (10 seconds). Bank may charge extra. |
| Cross-border, non-euro or non-SEPA | Single International Payment | Requires BIC. Higher fees, slower. |
| Future-dated payment | Single Domestic Scheduled Payment | Specify execution date |
| Recurring fixed payment | Single Domestic Periodic Payment | Standing order in UK. Specify frequency. |
| Multiple payments at once | Bulk payment | Use separate authorisation endpoint |
| Variable recurring (VRP) | Separate VRP flow | See VRP documentation |
Always check the institution’s supported features first using GET /institutions/{id}. Not all banks support all payment types. See Payment Features.
For detailed SEPA/domestic/international decision logic, see: European Payments Guide
Payee details by country
| Payer Country | Payee Country | Currency | Payee Account ID Required | Payee Name |
|---|
| UK | UK | GBP | SORT_CODE + ACCOUNT_NUMBER | Required |
| Any SEPA | Any SEPA | EUR | IBAN | Required |
| Any | EU/EEA (international) | Any | IBAN + BIC | Required |
Country-specific examples
UK Domestic
SEPA (Europe)
International
"payee": {
"name": "Jane Smith",
"accountIdentifications": [
{ "type": "SORT_CODE", "identification": "123456" },
{ "type": "ACCOUNT_NUMBER", "identification": "12345678" }
]
}
"payee": {
"name": "Hans Mueller",
"accountIdentifications": [
{ "type": "IBAN", "identification": "DE89370400440532013000" }
]
}
"payee": {
"name": "Pierre Dupont",
"accountIdentifications": [
{ "type": "IBAN", "identification": "FR7630006000011234567890189" },
{ "type": "BIC", "identification": "BNPAFRPP" }
]
}
Payer details
Payer requirements vary by country and institution.
UK: Payer details are usually not required. The bank knows the payer from the consent.
Europe (Berlin Group banks): Payer IBAN is often required. The bank needs to know which account to debit.
Some European banks also require: Payer name, payer address.
Payer requirements vary by institution, not just by country. Only request payer details when the institution requires them, as asking for unnecessary information adds friction to the user experience. For returning users, consider saving and pre-populating payer details to streamline subsequent payments. For institution-specific requirements, check the Yapily Console.
Payer examples
// Payer can be omitted for most UK payments.
// The bank determines the payer from the consent.
"payer": {
"name": "Max Mustermann",
"accountIdentifications": [
{ "type": "IBAN", "identification": "DE89370400440532013000" }
]
}
For institution-specific field requirements, log in to the Yapily Console to view detailed constraints.
Reference field
The reference field is the payment description visible on bank statements. This is what your customer will see when they review their transaction history.
Character limits vary by institution, from as low as 18 characters to 140. Some banks silently truncate long references, others reject the payment outright.
Recommendation: Keep references under 18 characters for maximum compatibility, or check institution-specific constraints in the Yapily Console.
Idempotency
The paymentIdempotencyId prevents duplicate payments if your request is retried.
How it works:
- Must be unique per payment attempt
- If the same ID is sent twice, Yapily returns the existing payment instead of creating a new one
- Generate a UUID for each payment attempt
Complete examples
UK Domestic Payment
SEPA Payment (Germany)
International Payment
{
"applicationUserId": "user-123",
"institutionId": "modelo-sandbox",
"callback": "https://your-app.com/callback",
"paymentRequest": {
"type": "DOMESTIC_PAYMENT",
"paymentIdempotencyId": "550e8400-e29b-41d4-a716-446655440000",
"amount": {
"amount": 10.00,
"currency": "GBP"
},
"reference": "Invoice 1234",
"payee": {
"name": "Jane Smith",
"accountIdentifications": [
{ "type": "SORT_CODE", "identification": "123456" },
{ "type": "ACCOUNT_NUMBER", "identification": "12345678" }
]
}
}
}
{
"applicationUserId": "user-456",
"institutionId": "commerzbank-sandbox",
"callback": "https://your-app.com/callback",
"paymentRequest": {
"type": "DOMESTIC_PAYMENT",
"paymentIdempotencyId": "660e8400-e29b-41d4-a716-446655440001",
"amount": {
"amount": 25.50,
"currency": "EUR"
},
"reference": "Order ABC",
"payer": {
"name": "Max Mustermann",
"accountIdentifications": [
{ "type": "IBAN", "identification": "DE89370400440532013000" }
]
},
"payee": {
"name": "Hans Mueller",
"accountIdentifications": [
{ "type": "IBAN", "identification": "DE44500105175407324931" }
]
}
}
}
{
"applicationUserId": "user-789",
"institutionId": "barclays-sandbox",
"callback": "https://your-app.com/callback",
"paymentRequest": {
"type": "INTERNATIONAL_PAYMENT",
"paymentIdempotencyId": "770e8400-e29b-41d4-a716-446655440002",
"amount": {
"amount": 100.00,
"currency": "EUR"
},
"reference": "Transfer",
"payee": {
"name": "Pierre Dupont",
"accountIdentifications": [
{ "type": "IBAN", "identification": "FR7630006000011234567890189" },
{ "type": "BIC", "identification": "BNPAFRPP" }
]
}
}
}
Common pitfalls
The following issues are frequently encountered when building payment requests:
- Payment rejected for missing payer details: Some European banks require payer IBAN or other details. Check institution requirements in the Yapily Console before building your payment form. Only collect what is needed to minimise friction.
- Reference too long: Keep under 18 characters for maximum compatibility across institutions.
- Wrong payment type for SEPA: If both accounts are in SEPA countries and currency is EUR, use
DOMESTIC_PAYMENT, not INTERNATIONAL_PAYMENT. Exception: NatWest Group requires INTERNATIONAL_PAYMENT for SEPA. See European Payments.
- Feature not supported: Always check
GET /institutions/{id} features array before initiating. See Payment Features.
- IBAN format rejected: IBAN formats are country-specific (different length and prefix per country). Validate format before sending.
- Duplicate payment created: Always include a unique
paymentIdempotencyId. If you retry without one, you may create duplicate payments.