Payment endpoints handle the complete payment processing workflow for car rental orders. The system supports multiple payment methods including credit card payments with 3D Secure authentication and credit limit payments for approved agencies.
Retrieve available installment options for credit card payments based on the card's BIN number and order amount. This endpoint helps customers understand payment options before completing their purchase.
POST /payment/installment-infoThis endpoint requires authentication. Include your JWT access token in the Authorization header:
Authorization: Bearer YOUR_ACCESS_TOKEN| Field | Type | Required | Description |
|---|---|---|---|
orderID | string | Yes | Order ID for which to calculate installments |
binNumber | string | Yes | First 6 digits of the credit card number |
curl -X POST https://api.pro.yolcu360.com/api/v1/payment/installment-info \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-d '{
"orderID": "order_123456789",
"binNumber": "543210"
}'Success Response (200 OK):
{
"bankCode": 12,
"bankName": "Example Bank",
"binNumber": "543210",
"cardAssociation": "MasterCard",
"cardFamily": "World",
"cardType": "credit",
"shouldForceTo3D": true,
"supportedCurrencies": [
"TRY",
"USD",
"EUR"
],
"installmentPrices": [
{
"number": 1,
"price": {
"amount": 54500,
"currency": "TRY"
},
"totalPrice": {
"amount": 54500,
"currency": "TRY"
}
},
{
"number": 3,
"price": {
"amount": 18500,
"currency": "TRY"
},
"totalPrice": {
"amount": 55500,
"currency": "TRY"
}
},
{
"number": 6,
"price": {
"amount": 9500,
"currency": "TRY"
},
"totalPrice": {
"amount": 57000,
"currency": "TRY"
}
},
{
"number": 12,
"price": {
"amount": 5000,
"currency": "TRY"
},
"totalPrice": {
"amount": 60000,
"currency": "TRY"
}
}
]
}| Field | Type | Description |
|---|---|---|
bankCode | integer | Bank identifier code |
bankName | string | Bank name |
binNumber | string | BIN number used for the query |
cardAssociation | string | Card network (Visa, MasterCard, etc.) |
cardFamily | string | Card family (Classic, Gold, Platinum, etc.) |
cardType | string | Card type (credit, debit) |
shouldForceTo3D | boolean | Whether 3D Secure is mandatory for this card |
supportedCurrencies | array | Currencies supported by the card |
installmentPrices | array | Available installment options |
installmentPrices[].number | integer | Number of installments |
installmentPrices[].price | object | Monthly payment amount |
installmentPrices[].totalPrice | object | Total amount with interest |
Retrieve the calling agency's remaining cari (running credit) limits, so agencies integrating via the API can check available credit before attempting a credit limit payment, instead of discovering an insufficient limit only when POST /payment/pay fails.
The organization is always resolved from your access token — you can only ever see your own agency's limits, and there is no way to query another agency's limits. This endpoint is never cached; it always reflects your agency's current limits.
GET /payment/limitsThis endpoint requires authentication. Include your JWT access token in the Authorization header:
Authorization: Bearer YOUR_ACCESS_TOKENcurl -X GET https://api.pro.yolcu360.com/api/v1/payment/limits \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"Success Response (200 OK):
An organization can have cari balances in more than one currency, and more than one active balance in the same currency. These are never merged: every active balance is returned as its own entry in remaining, identified by its id, so the same currency can appear more than once and you can still tell which balance is which.
{
"remaining": [
{
"id": 338,
"amount": 5000000,
"currency": "TRY"
},
{
"id": 339,
"amount": 2500000,
"currency": "TRY"
},
{
"id": 4,
"amount": 100000,
"currency": "USD"
},
{
"id": 3,
"amount": 750000,
"currency": "EUR"
}
]
}If your agency has no cari defined, remaining is an empty array rather than an error.
| Field | Type | Description |
|---|---|---|
remaining | array | One entry per active cari balance, never merged by currency. |
remaining[].id | integer | The cari balance's own ID, stable and unique per record — use it to tell apart multiple balances in the same currency. |
remaining[].amount | integer | Remaining amount, in the smallest unit of its currency. |
remaining[].currency | string | Currency code: TRY, USD, EUR, or GBP. |
Note: the response only ever contains the remaining amount. Total limit, amount used, limit status, and transaction/statement detail are not part of this endpoint's response.
Process payment for an order using either credit card or credit limit. This endpoint handles both 2D and 3D Secure credit card payments, as well as credit limit payments for approved agencies.
POST /payment/payThis endpoint requires authentication. Include your JWT access token in the Authorization header.
In staging, payment rules are different:
- In staging, payments are supported only for vendor
Yolcutest. - If a payment is blocked due to this rule, API returns:
code:6008description:Payments in the staging environment are only supported for the "Yolcutest" vendor.
| Field | Type | Required | Description |
|---|---|---|---|
orderID | string | Yes | Order ID to process payment for |
paymentType | string | Yes | Payment method: creditCard or limit |
payWithCard | object | Conditional | Credit card details (required if paymentType is creditCard) |
| Field | Type | Required | Description |
|---|---|---|---|
cardNumber | string | Yes | Credit card number (PCI compliant handling) |
expireMonth | string | Yes | Card expiration month (01-12) |
expireYear | string | Yes | Card expiration year (YYYY) |
cardHolderName | string | Yes | Name as it appears on the card |
cvc | string | Yes | 3-digit security code |
installment | integer | Yes | Number of installments (1 for single payment) |
isWith3DSecure | boolean | Yes | Whether to use 3D Secure authentication |
callbackUrl | string | Yes | URL for 3D Secure completion callback |
curl -X POST https://api.pro.yolcu360.com/api/v1/payment/pay \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-d '{
"orderID": "order_123456789",
"paymentType": "creditCard",
"payWithCard": {
"cardNumber": "4242424242424242",
"expireMonth": "12",
"expireYear": "2025",
"cardHolderName": "John Doe",
"cvc": "123",
"installment": 3,
"isWith3DSecure": true,
"callbackUrl": "https://yoursite.com/payment/callback"
}
}'curl -X POST https://api.pro.yolcu360.com/api/v1/payment/pay \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-d '{
"orderID": "order_123456789",
"paymentType": "limit"
}'{
"status": "success",
"is3dsSecure": false,
"threeDSHtmlContent": null
}{
"status": "redirect_required",
"is3dsSecure": true,
"threeDSHtmlContent": "<!DOCTYPE html><html><head><title>3D Secure</title></head><body><form id='threeDSForm' action='https://3ds.bank.com/auth' method='POST'>...</form><script>document.getElementById('threeDSForm').submit();</script></body></html>"
}{
"status": "success",
"is3dsSecure": false,
"threeDSHtmlContent": null
}| Field | Type | Description |
|---|---|---|
status | string | Payment status (success, redirect_required, failed) |
is3dsSecure | boolean | Whether the payment requires 3D Secure authentication |
threeDSHtmlContent | string | HTML content for 3D Secure redirect (if required) |
After the customer completes the bank's challenge, the payment is finalized, the reservation is triggered, and the customer's browser is redirected (HTTP 303) to the callbackUrl you supplied in payWithCard. Your callbackUrl receives the customer with these query parameters appended:
| Parameter | Type | Description |
|---|---|---|
status | string | success or failure (payment and reservation outcome) |
orderId | string | Order identifier |
transactionId | string | Bank transaction identifier |
description | string | Human-readable outcome description |
Example:
https://yoursite.com/payment/callback?status=success&orderId=order_123456789&transactionId=txn_789012&description=Payment+is+successfulThe status parameter covers both the payment and the reservation. A failure can also mean the card was charged but the reservation failed, in which case description reads Payment is successful but reservation failed. Always confirm the final order state with GET /order/{orderID} after receiving the callback.
- Card Types: Visa, MasterCard, American Express
- 3D Secure: Optional or mandatory based on card and amount
- Installments: Multiple installment options based on card type
- Currencies: TRY, USD, EUR (depending on card support)
- Customer submits payment with 3D Secure enabled
- API returns HTML content for bank authentication
- Customer completes authentication on bank's website
- Bank redirects to the 3D Secure callback endpoint
- Payment is finalized and customer is redirected to success page
- PCI Compliance: All card data is handled securely
- Tokenization: Card numbers are never stored in plain text
- SSL/TLS: All communications are encrypted
- Fraud Detection: Built-in fraud protection mechanisms
- Available for agencies with approved credit limits
- Requires active credit agreement
- Subject to available credit balance
- Immediate payment processing
- No additional authentication required
- Automatic credit limit adjustment
- Billing occurs according to credit terms
- BIN Validation: Always check installment options before payment
- 3D Secure: Use 3D Secure for enhanced security
- Error Handling: Implement robust error handling for payment failures
- Timeout Management: Handle payment timeouts gracefully
- PCI Compliance: Ensure your integration meets PCI DSS requirements
- Data Protection: Never log or store sensitive card information
- HTTPS Only: Always use HTTPS for payment communications
- Token Management: Securely handle payment tokens and callbacks
- Progress Indicators: Show clear payment progress to users
- Error Messages: Provide helpful error messages for failed payments
- Retry Logic: Allow users to retry failed payments
- Confirmation: Always show payment confirmation to users
400 Bad Request: Invalid payment data or missing required fields401 Unauthorized: Authentication required or token expired402 Payment Required: Insufficient credit limit or card declined404 Not Found: Order not found or payment already processed422 Unprocessable Entity: Payment validation errors500 Internal Server Error: Payment processor error
{
"code": 2001,
"description": "Credit card declined",
"details": {
"field": "cardNumber",
"message": "The card was declined by the bank",
"bankCode": "05",
"bankMessage": "Do not honor"
}
}| Code | Description | Action |
|---|---|---|
| 2001 | Card declined | Try different card or payment method |
| 2002 | Insufficient funds | Check card balance or use different card |
| 2003 | Expired card | Update card expiration date |
| 2004 | Invalid card number | Verify card number is correct |
| 2005 | Invalid CVC | Check security code |
| 2006 | 3D Secure failed | Retry with correct authentication |
| 2007 | Credit limit exceeded | Use alternative payment method |
| 2008 | Payment timeout | Retry the payment |
| 6008 | Staging vendor guard | Use the Yolcutest vendor in the staging environment |
// Step 1: Get installment options
async function getInstallmentOptions(orderID, cardNumber) {
const binNumber = cardNumber.substring(0, 6);
const response = await fetch('/api/v1/payment/installment-info', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${accessToken}`
},
body: JSON.stringify({
orderID: orderID,
binNumber: binNumber
})
});
return await response.json();
}
// Step 2: Process payment
async function processPayment(orderID, cardDetails, installmentOption) {
const paymentData = {
orderID: orderID,
paymentType: 'creditCard',
payWithCard: {
cardNumber: cardDetails.number,
expireMonth: cardDetails.expireMonth,
expireYear: cardDetails.expireYear,
cardHolderName: cardDetails.holderName,
cvc: cardDetails.cvc,
installment: installmentOption.number,
isWith3DSecure: true,
callbackUrl: `${window.location.origin}/payment/callback`
}
};
const response = await fetch('/api/v1/payment/pay', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${accessToken}`
},
body: JSON.stringify(paymentData)
});
const result = await response.json();
if (result.is3dsSecure) {
// Handle 3D Secure redirect
document.body.innerHTML = result.threeDSHtmlContent;
} else {
// Payment completed without 3D Secure
handlePaymentSuccess(result);
}
}
// Step 3: Handle 3D Secure callback
function handle3DSCallback() {
const urlParams = new URLSearchParams(window.location.search);
const orderId = urlParams.get('orderId');
const status = urlParams.get('status');
if (status === 'success') {
handlePaymentSuccess();
} else {
handlePaymentFailure();
}
}async function processCreditLimitPayment(orderID) {
const response = await fetch('/api/v1/payment/pay', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${accessToken}`
},
body: JSON.stringify({
orderID: orderID,
paymentType: 'limit'
})
});
if (!response.ok) {
const error = await response.json();
throw new Error(`Payment failed: ${error.description}`);
}
return await response.json();
}Payment endpoints are subject to rate limiting:
- Installment info: Maximum 30 requests per minute per user
- Process payment: Maximum 10 requests per minute per user
- 3D Secure callback: Maximum 100 requests per minute per order
Implement appropriate retry logic and monitor rate limit headers in responses.