Merchant API Documentation

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

Base URL: https://api.veltorapay.com
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": "VeltoraPay 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": "VeltoraPay 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

VeltoraPay 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": "VeltoraPay 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, VeltoraPay 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

VeltoraPay 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 VeltoraPay 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.