API response language

Merchant API Documentation

Direct API integration for deposits, withdrawals, and real-time callbacks.

Base URL: https://84.32.244.221:8446
All 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.

HeaderRequiredDescription
X-API-KeyRequiredYour API key. Can also contain key:secret combined format.
X-API-SecretOptionalYour API secret. If omitted, include it in X-API-Key as key:secret.
Content-TypeRequiredapplication/json
IP Whitelisting: If configured for your merchant, only requests from your whitelisted IPs will be accepted. Contact your account manager to update allowed IPs.
Example Headers
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

FieldTypeRequiredDescription
amountdecimalRequiredDeposit amount in TRY (0.01 – 10,000,000)
senderNamestringOptionalSender's full name. Alias: userName
clientTokenstringOptionalYour unique transaction reference. Alias: transactionId
userIdstringOptionalCustomer user identifier (max 120 chars)
Request
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"
}
Save the 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

FieldTypeRequiredDescription
tokenstringRequiredThe deposit token returned from create-deposit
Response — 200 OK
{
  "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

FieldTypeRequiredDescription
amountdecimalRequiredWithdraw amount in TRY (0.01 – 10,000,000)
recipientNamestringRequiredRecipient's full name
recipientIbanstringRequiredRecipient's IBAN
recipientBankstringOptionalRecipient's bank name
clientTokenstringOptionalYour unique transaction reference
userIdstringOptionalCustomer user identifier (max 120 chars)
Request
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"
}
Balance Guard: If your merchant treasury (kasa) balance is insufficient, the withdraw will be created with Failed status and a rejection callback will be sent automatically.

Check Withdraw

POST/dealer/{dealerName}/check-withdraw

Request Body

FieldTypeRequiredDescription
tokenstringRequiredThe withdraw token returned from create-withdraw
Response — 200 OK
{
  "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

ParamTypeDefaultDescription
statusstringFilter by status: Pending, Matched, Rejected, Timeout, ManualApproved
fromDatedateStart date (YYYY-MM-DD)
toDatedateEnd date (YYYY-MM-DD)
pageint1Page number
pageSizeint50Items 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 Payload
POST {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

StatusMeaning
matchedDeposit matched or manually approved — funds received
cancelledDeposit was rejected
timeoutDeposit timed out — no matching transfer detected

Retry Policy

If your callback URL returns a non-2xx response, KafilPay retries with exponential backoff:

AttemptDelay
1Immediate
21 minute
35 minutes
415 minutes
530 minutes
660 minutes
Custom Templates: You can configure a custom callback JSON template with {{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 Payload
POST {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

StatusMeaning
CompletedWithdrawal succeeded — funds sent
RejectedWithdrawal failed or rejected
TimeoutWithdrawal timed out

Status Reference

Deposit Statuses

StatusValueDescription
Pending0Waiting for bank transfer
Matched1Auto-matched with bank transaction
Rejected2Rejected by admin or system
Timeout3Expired — no match found
ManualApproved4Manually approved by operator

Withdraw Statuses

StatusValueDescription
Pending0Queued for processing
InProgress1Being processed by payment source
Succeeded2Funds sent to recipient
Failed3Rejected or insufficient balance
Timeout4Processing timed out

Error Codes

HTTPCodeDescription
400invalid_bodyRequest body is invalid or missing
400missing_fieldA required field is missing
400invalid_amountAmount is not a valid number
400amount_below_minimumAmount is below minimum threshold
400amount_above_maximumAmount exceeds maximum threshold
400iban_requiredRecipient IBAN is missing (withdraw)
401unauthorizedInvalid or missing API key/secret
403ip_not_whitelistedRequest IP is not in whitelist
403user_bannedThe userId is banned
404not_foundToken or resource not found
409duplicate_tokenclientToken already exists with active status
409no_eligible_accountNo suitable bank account available
429rate_limitedToo many requests
503no_available_sourceNo 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.

Callback endpoints and status polling are excluded from rate limiting.

Security Best Practices

  1. IP Whitelisting: Configure your server IPs in the merchant panel. Only accept KafilPay callbacks from our server IP.
  2. Token Verification: Always cross-check token and clientToken in callbacks against your records.
  3. Status Verification: After receiving a callback, call check-deposit or check-withdraw to confirm the status independently.
  4. HTTPS Only: All callback URLs must use HTTPS.
  5. 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&currency=SYP
GET /wallet-api/views/end-of-day?walletId=WALLET_ID&currency=SYP&date=2026-09-12
GET /wallet-api/views/balance?walletId=WALLET_ID&currency=SYP
GET /wallet-api/views/statement?walletId=WALLET_ID&currency=SYP&page=1
GET /wallet-api/views/reports?walletId=WALLET_ID&currency=SYP&fromDate=2026-09-01&toDate=2026-09-30
GET /wallet-api/views/deposits?walletId=WALLET_ID&currency=SYP
GET /wallet-api/views/withdraws?walletId=WALLET_ID&currency=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.