API response language
Merchant API Documentation
Direct API integration for deposits, withdrawals, and real-time callbacks.
https://84.32.244.221:8446All endpoints use the
/dealer/{dealerName} prefix where {dealerName} is your assigned merchant identifier.
Authentication
All API requests require header-based authentication using your API key and secret.
| Header | Required | Description |
|---|---|---|
| X-API-Key | Required | Your API key. Can also contain key:secret combined format. |
| X-API-Secret | Optional | Your API secret. If omitted, include it in X-API-Key as key:secret. |
| Content-Type | Required | application/json |
X-API-Key: your-api-key
X-API-Secret: your-api-secret
Content-Type: application/json
Create Deposit
POST/dealer/{dealerName}/create-deposit
Creates a new deposit request and returns the assigned bank account details for the customer to transfer funds to.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| amount | decimal | Required | Deposit amount in TRY (0.01 – 10,000,000) |
| senderName | string | Optional | Sender's full name. Alias: userName |
| clientToken | string | Optional | Your unique transaction reference. Alias: transactionId |
| userId | string | Optional | Customer user identifier (max 120 chars) |
POST /dealer/yourmerchant/create-deposit
Content-Type: application/json
X-API-Key: your-api-key
X-API-Secret: your-api-secret
{
"amount": 1000.00,
"senderName": "Ahmet Yilmaz",
"clientToken": "TXN-20260331-001",
"userId": "user-12345"
}
Response — 200 OK
{
"success": true,
"token": "c3d4e5f6-7890-abcd-ef12-345678901234",
"amount": 1000.00,
"senderName": "Ahmet Yilmaz",
"source": "Source-1",
"assignedTo": {
"walletId": "EXT-WALLET-001",
"accountHolder": "KafilPay A.S.",
"bank": "Ziraat Bankasi",
"iban": "TR12 0001 0012 3456 7890 1234 56"
},
"createdAt": "2026-03-31T10:00:00Z"
}
token value — you'll need it to check deposit status and match callbacks.
Check Deposit
POST/dealer/{dealerName}/check-deposit
Check the status of a deposit request by its token.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| token | string | Required | The deposit token returned from create-deposit |
{
"token": "c3d4e5f6-...",
"clientToken": "TXN-20260331-001",
"amount": 1000.00,
"senderName": "Ahmet Yilmaz",
"status": "Matched",
"iban": "TR12 0001 0012 3456 7890 1234 56",
"accountHolder": "KafilPay A.S.",
"bank": "Ziraat Bankasi",
"source": "Source-1",
"matchedAt": "2026-03-31T10:05:30Z",
"createdAt": "2026-03-31T10:00:00Z",
"updatedAt": "2026-03-31T10:05:30Z"
}
Create Withdraw
POST/dealer/{dealerName}/create-withdraw
Creates a new withdrawal request. The system selects the optimal source and processes the payment to the customer's bank account.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| amount | decimal | Required | Withdraw amount in TRY (0.01 – 10,000,000) |
| recipientName | string | Required | Recipient's full name |
| recipientIban | string | Required | Recipient's IBAN |
| recipientBank | string | Optional | Recipient's bank name |
| clientToken | string | Optional | Your unique transaction reference |
| userId | string | Optional | Customer user identifier (max 120 chars) |
POST /dealer/yourmerchant/create-withdraw
Content-Type: application/json
X-API-Key: your-api-key
X-API-Secret: your-api-secret
{
"amount": 500.00,
"recipientName": "Mehmet Demir",
"recipientIban": "TR76 0006 2000 1234 5678 9012 34",
"recipientBank": "Garanti BBVA",
"clientToken": "WD-20260331-001"
}
Response — 200 OK
{
"success": true,
"token": "a1b2c3d4-5678-...",
"amount": 500.00,
"recipientName": "Mehmet Demir",
"recipientIban": "TR76 0006 2000 1234 5678 9012 34",
"source": "Pool",
"status": "Pending",
"createdAt": "2026-03-31T11:00:00Z"
}
Failed status and a rejection callback will be sent automatically.
Check Withdraw
POST/dealer/{dealerName}/check-withdraw
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| token | string | Required | The withdraw token returned from create-withdraw |
{
"token": "a1b2c3d4-...",
"clientToken": "WD-20260331-001",
"amount": 500.00,
"recipientName": "Mehmet Demir",
"recipientIban": "TR76 0006 2000 1234 5678 9012 34",
"recipientBank": "Garanti BBVA",
"status": "Succeeded",
"externalStatus": "Succeeded",
"source": "Pool",
"createdAt": "2026-03-31T11:00:00Z",
"updatedAt": "2026-03-31T11:02:30Z"
}
List Deposits
GET/dealer/{dealerName}/deposits
Paginated list of your deposit requests.
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| status | string | — | Filter by status: Pending, Matched, Rejected, Timeout, ManualApproved |
| fromDate | date | — | Start date (YYYY-MM-DD) |
| toDate | date | — | End date (YYYY-MM-DD) |
| page | int | 1 | Page number |
| pageSize | int | 50 | Items per page (max 200) |
List Withdraws
GET/dealer/{dealerName}/withdraws
Paginated list of your withdraw requests. Same query parameters as List Deposits.
Deposit Callbacks
KafilPay sends HTTP POST callbacks to your configured Deposit Callback URL when a deposit status changes.
Callback PayloadPOST {your_deposit_callback_url}
Content-Type: application/json
{
"event": "deposit.status_changed",
"token": "c3d4e5f6-...",
"clientToken": "TXN-20260331-001",
"status": "matched",
"amount": 1000.00,
"senderName": "Ahmet Yilmaz",
"customerName": "Ahmet Yilmaz",
"iban": "TR12 0001 0012 3456 7890 1234 56",
"accountHolder": "KafilPay A.S.",
"bank": "Ziraat Bankasi",
"source": "Source-1",
"matchedAt": "2026-03-31T10:05:30Z",
"timestamp": "2026-03-31T10:05:30Z"
}
Callback Status Values
| Status | Meaning |
|---|---|
| matched | Deposit matched or manually approved — funds received |
| cancelled | Deposit was rejected |
| timeout | Deposit timed out — no matching transfer detected |
Retry Policy
If your callback URL returns a non-2xx response, KafilPay retries with exponential backoff:
| Attempt | Delay |
|---|---|
| 1 | Immediate |
| 2 | 1 minute |
| 3 | 5 minutes |
| 4 | 15 minutes |
| 5 | 30 minutes |
| 6 | 60 minutes |
{{placeholder}} tokens. Contact your account manager for setup.
Withdraw Callbacks
KafilPay sends HTTP POST callbacks to your configured Withdraw Callback URL when a withdrawal status changes.
Callback PayloadPOST {your_withdraw_callback_url}
Content-Type: application/json
{
"event": "withdraw.status_changed",
"token": "a1b2c3d4-...",
"clientToken": "WD-20260331-001",
"status": "Completed",
"externalStatus": "Succeeded",
"amount": 500.00,
"recipientName": "Mehmet Demir",
"recipientIban": "TR76 0006 2000 1234 5678 9012 34",
"recipientBank": "Garanti BBVA",
"source": "Pool",
"timestamp": "2026-03-31T11:02:30Z"
}
Callback Status Values
| Status | Meaning |
|---|---|
| Completed | Withdrawal succeeded — funds sent |
| Rejected | Withdrawal failed or rejected |
| Timeout | Withdrawal timed out |
Status Reference
Deposit Statuses
| Status | Value | Description |
|---|---|---|
| Pending | 0 | Waiting for bank transfer |
| Matched | 1 | Auto-matched with bank transaction |
| Rejected | 2 | Rejected by admin or system |
| Timeout | 3 | Expired — no match found |
| ManualApproved | 4 | Manually approved by operator |
Withdraw Statuses
| Status | Value | Description |
|---|---|---|
| Pending | 0 | Queued for processing |
| InProgress | 1 | Being processed by payment source |
| Succeeded | 2 | Funds sent to recipient |
| Failed | 3 | Rejected or insufficient balance |
| Timeout | 4 | Processing timed out |
Error Codes
| HTTP | Code | Description |
|---|---|---|
| 400 | invalid_body | Request body is invalid or missing |
| 400 | missing_field | A required field is missing |
| 400 | invalid_amount | Amount is not a valid number |
| 400 | amount_below_minimum | Amount is below minimum threshold |
| 400 | amount_above_maximum | Amount exceeds maximum threshold |
| 400 | iban_required | Recipient IBAN is missing (withdraw) |
| 401 | unauthorized | Invalid or missing API key/secret |
| 403 | ip_not_whitelisted | Request IP is not in whitelist |
| 403 | user_banned | The userId is banned |
| 404 | not_found | Token or resource not found |
| 409 | duplicate_token | clientToken already exists with active status |
| 409 | no_eligible_account | No suitable bank account available |
| 429 | rate_limited | Too many requests |
| 503 | no_available_source | No payment source available |
Rate Limiting
API requests are rate-limited to 120 requests per 60 seconds per IP address. Exceeding this limit returns 429 Too Many Requests.
Security Best Practices
- IP Whitelisting: Configure your server IPs in the merchant panel. Only accept KafilPay callbacks from our server IP.
- Token Verification: Always cross-check
tokenandclientTokenin callbacks against your records. - Status Verification: After receiving a callback, call
check-depositorcheck-withdrawto confirm the status independently. - HTTPS Only: All callback URLs must use HTTPS.
- Idempotency: Design your callback handler to be idempotent — you may receive the same callback multiple times.
Para Birimleri
API isteklerinde currency alanı veya X-Currency başlığı kullanın.
X-Currency: TRY
{"amount": 125.50, "currency": "TRY"}Yatırım için transactionType: Deposit, çekim için Withdraw gönderilir. Çekimde recipientName ve recipientAddress zorunludur; kullanılabilir cüzdan bakiyesi kontrol edilir ve bekleyen tutar ayrılır. Bu uç talep oluşturur, harici para göndermez.
Cüzdan API — Yönetim, bakiye ve döküm
Merchant isteklerinde X-Merchant-Name ve X-Api-Key başlıklarını gönderin. Admin Bearer oturumu kullanır. Merchant yalnızca kendi cüzdanlarını yönetebilir.
Oluşturma için id göndermeyin; düzenleme için id ekleyin. Admin oluştururken merchantId zorunludur. Bağlantı alanları attributes ile gönderilir; secret değerler yanıtlarda dönmez. Boş secret mevcut değeri korur.
GET /wallet-api/
POST /wallet-api/wallets
{"name":{"tr":"Cüzdan","en":"Wallet","ar":"محفظة"},"currencies":["USD","SYP"],"connector":"manual","address":"PAYMENT-ADDRESS","active":true}
GET /wallet-api/wallets/:id
POST /wallet-api/wallets/:id/status
{"active":false}
POST /wallet-api/wallets/:id/payment
{"title":{"tr":"Yatırım","en":"Deposit","ar":"إيداع"},"walletAddress":"PAYMENT-ADDRESS","fields":[],"steps":[]}
GET /wallet-api/views/dashboard?walletId=WALLET_ID¤cy=SYP
GET /wallet-api/views/end-of-day?walletId=WALLET_ID¤cy=SYP&date=2026-09-12
GET /wallet-api/views/balance?walletId=WALLET_ID¤cy=SYP
GET /wallet-api/views/statement?walletId=WALLET_ID¤cy=SYP&page=1
GET /wallet-api/views/reports?walletId=WALLET_ID¤cy=SYP&fromDate=2026-09-01&toDate=2026-09-30
GET /wallet-api/views/deposits?walletId=WALLET_ID¤cy=SYP
GET /wallet-api/views/withdraws?walletId=WALLET_ID¤cy=SYP
GET /wallet-api/routing
POST /wallet-api/routing
{ "enabled": true, "currency": "USD", "threshold": "1000", "walletIds": ["FIRST_WALLET", "NEXT_WALLET"] }
GET /wallet-api/wallet-balances?walletId=WALLET_ID
GET /wallet-api/wallet-statement?walletId=WALLET_ID
GET /wallet-api/wallet-reports?walletId=WALLET_ID
{"walletIds":["WALLET_ID"],"balances":{"1:WALLET_ID:USD":"125"},"requests":[],"ledger":[],"pending":0,"verified":0}Bakiyeler en küçük para birimi cinsinden tamsayı metindir (USD 125 = 1.25 USD). Her merchant, cüzdan ve para birimi ayrıdır. Yalnızca doğrulanmış hareketler bakiyeye dahildir. Test kayıtları gerçek harici servis bakiyesi değildir.
Geçiş kuralını merchant kendi oturumuyla yönetir. Admin GET isteğinde merchantId sorgusu, POST gövdesinde merchantId kullanır. walletIds öncelik sırasıdır. Onaylanmış bakiye eşiğe eşit veya üzerindeyse sonraki uygun cüzdan sunulur; bekleyen talepler sayılmaz. Kur bilinmiyorsa cüzdan atlanır. Tümü eşikteyse uygun cüzdan dönmez. Talep gönderiminde seçim yeniden kontrol edilir; wallet_unavailable yanıtında formu yenileyin. Dil için lang veya Accept-Language kullanılabilir.
Yatırım formu, kur teklifi ve talep akışı mevcut /form/:id, /quote, /files ve /requests uçlarında sürer. Liste yanıtındaki boxes bağlantısı geriye uyumluluk içindir. walletVersion ve version değerlerini aynen iletin. /requests için Idempotency-Key zorunludur. Checkout oturumu cüzdan yönetimine veya raporlara erişemez.