API Documentation

Authentication

All API requests must be authenticated using API Key and API Secret headers.

Headers:

Header Name Description
X-API-KEY Your API Key
X-API-SECRET Your API Secret

These credentials are unique to each merchant and must be included in every API request. Requests without valid credentials will receive a 401 Unauthorized response. You can get credentials from Settings page in our dashboard.

Example:

curl -X POST https://api.example.com/api/payment \
     -H "Content-Type: application/json" \
     -H "X-API-KEY: your_api_key_here" \
     -H "X-API-SECRET: your_api_secret_here" \
     -d '{"orderId": "ORD-12345", ...}'
    

Ensure that your API Key and API Secret are kept secure and not shared publicly.

Payment

Endpoint: POST /api/payment

Description: Process a payment transaction

Request Body:

{
  "orderId": "string",
  "amount": "number",
  "currency": "string",
  "cardHolderName": "string",
  "pan": "string",
  "expiryMonth": "string",
  "expiryYear": "string",
  "cvv": "string",
  "requestIp": "string",
  "requestPort": "number",
  "customerId": "string"
}
        

Field Descriptions:

Field Description Example
orderId Client's tracking number for the order ORD-12345
amount Transaction amount 100.50
currency Currency code TRY
cardHolderName Name of the card holder John Doe
pan Primary Account Number (card number) 5421190122090656
expiryMonth Card expiry month (2 digits) 04
expiryYear Card expiry year (2 digits) 28
cvv Card Verification Value 916
requestIp IP address of the client making the request 192.168.1.1
requestPort Port number of the client making the request 8080
customerId Optional unique identifier for the customer CUST-12345

Response:

Returns an ApiPaymentResponse object with payment details.

{
  "paymentId": "UUID",
  "orderId": "string",
  "amount": "number",
  "installmentCount": "number",
  "currency": "string",
  "merchantCommission": "number",
  "status": "string",
  "transactionType": "string",
  "paymentDate": "date",
  "cardHolderName": "string",
  "pan": "string",
  "domInt": "string",
  "cardScheme": "string",
  "cardType": "string",
  "cardSubType": "string",
  "loyaltyCode": "string",
  "externalTransactionId": "string",
  "authCode": "string",
  "resultCode": "string",
  "resultMessage": "string",
  "customerId": "string"
}
        

Response Field Descriptions:

Field Description Example
paymentId Unique identifier for the payment 123e4567-e89b-12d3-a456-426614174000
orderId Client's tracking number for the order ORD-12345
amount Transaction amount 100.50
installmentCount Number of installments 3
currency Currency code TRY
merchantCommission Commission charged to the merchant 2.50
status Payment status (SUCCESS, FAILED, ENROLLED, PENDING_APPROVAL, CANCELLED, CAPTURED, REJECTED) SUCCESS
transactionType Transaction type (SALE, REFUND) SALE
paymentDate Date and time of the payment 2023-05-01T14:30:00Z
cardHolderName Name of the card holder John Doe
pan Masked Primary Account Number 411111******1111
domInt Domestic or International transaction DOM
cardScheme Card scheme (e.g., VISA, MASTERCARD) VISA
cardType Type of card (e.g., CREDIT, DEBIT) CREDIT
loyaltyCode Loyalty program code (if applicable) GOLD123
externalTransactionId Transaction ID from the payment provider EXT123456789
authCode Authorization code from the payment provider AUTH987654
resultCode Result code from the payment provider SUCCESS
resultMessage Result message from the payment provider Successful
customerId Unique identifier for the customer (if provided) CUST-12345

Pre-Authorization

Endpoint: POST /api/pre-authorization

Description: Process a pre-authorization transaction

Request Body:

{
  "orderId": "string",
  "amount": "number",
  "currency": "string",
  "cardHolderName": "string",
  "pan": "string",
  "expiryMonth": "string",
  "expiryYear": "string",
  "cvv": "string",
  "requestIp": "string",
  "requestPort": "number",
  "customerId": "string"
}
        

Field Descriptions:

Field Description Example
orderId Client's tracking number for the order ORD-12345
amount Transaction amount 100.50
currency Currency code TRY
cardHolderName Name of the card holder John Doe
pan Primary Account Number (card number) 5421190122090656
expiryMonth Card expiry month (2 digits) 04
expiryYear Card expiry year (2 digits) 28
cvv Card Verification Value 916
requestIp IP address of the client making the request 192.168.1.1
requestPort Port number of the client making the request 8080
customerId Optional unique identifier for the customer CUST-12345

Response:

Returns an ApiPaymentResponse object with pre-authorization details (same as Payment response).

Capture Pre-Authorization

Endpoint: POST /api/pre-authorization/{paymentId}/capture

Description: Capture a previously authorized payment

Path Parameters:

Request Body:

{
  "amount": "number",
  "currency": "string"
}
        

Field Descriptions:

Field Description Example
amount Amount to capture (can be less than or equal to the pre-authorized amount) 90.00
currency Currency code TRY

Response:

Returns an ApiPaymentResponse object with capture details (same as Payment response).

3D Secure Payment

Description: Process a 3D Secure payment

1. Initiate 3D Secure Enrollment

Endpoint: POST /api/3ds

Request Body:

{
  "orderId": "string",
  "amount": "number",
  "currency": "string",
  "installmentCount": "number",
  "interestPaidByCustomer": "boolean",
  "cardHolderName": "string",
  "pan": "string",
  "expiryMonth": "string",
  "expiryYear": "string",
  "cvv": "string",
  "successUrl": "string",
  "failureUrl": "string",
  "requestIp": "string",
  "requestPort": "number",
  "customerId": "string"
}
        

Field Descriptions:

Field Description Example
orderId Client's tracking number for the order ORD-12345
amount Transaction amount 100.50
currency Currency code TRY
installmentCount Number of installments (optional, default 1). You should check available installment options via Installment Options API before setting this value. 3
interestPaidByCustomer Whether interest is paid by customer (optional) true
cardHolderName Name of the card holder John Doe
pan Primary Account Number (card number) 5421190122090656
expiryMonth Card expiry month (2 digits) 04
expiryYear Card expiry year (2 digits) 28
cvv Card Verification Value 916
successUrl URL to redirect after successful 3D Secure authentication https://example.com/3ds/success
failureUrl URL to redirect after failed 3D Secure authentication https://example.com/3ds/failure
requestIp IP address of the client making the request 192.168.1.1
requestPort Port number of the client making the request 8080
customerId Optional unique identifier for the customer CUST-12345

Response:

{
  "paymentId": "UUID",
  "success": "boolean",
  "resultCode": "string",
  "resultMessage": "string",
  "htmlContent": "string"
}
        

Response Field Descriptions:

Field Description Example
paymentId Unique identifier for the payment 123e4567-e89b-12d3-a456-426614174000
success Indicates if the enrollment was successful true
resultCode Result code from the 3D Secure enrollment SUCCESS
resultMessage Result message from the 3D Secure enrollment Successful
htmlContent HTML content to be presented to the end user for 3D Secure authentication <form action="https://3ds.example.com" method="POST">...</form>

2. Present 3D Secure Authentication

Present the returned htmlContent to the end user. This typically involves rendering an iframe or redirecting the user to complete the 3D Secure authentication.

3. Handle 3D Secure Callback

After the authentication process, the payment provider will call the provided callback URLs (success or failure) with relevant parameters posted as form data.

Callback Form Data Parameters:

Field Description Example
paymentId Unique identifier for the payment 123e4567-e89b-12d3-a456-426614174000
securityKey Security key received from the 3D Secure authentication process 3DS_AUTH_KEY_123456

4. Complete 3D Secure Payment

Endpoint: POST /api/3ds/{paymentId}/complete

Path Parameters:

Request Body:

{
  "securityKey": "string"
}
        

Field Descriptions:

Field Description Example
securityKey Security key received from the 3D Secure authentication process 3DS_AUTH_KEY_123456

Response:

Returns an ApiPaymentResponse object with completed 3D Secure payment details (same as Payment response).

3D Secure Payment Flow:

  1. Call the Initiate 3D Secure Enrollment endpoint with the payment details and callback URLs.
  2. Present the returned htmlContent to the end user for 3D Secure authentication.
  3. Wait for the callback to be triggered after the authentication process.
  4. When the callback is received, extract the paymentId and securityKey from the form data.
  5. Call the Complete 3D Secure Payment endpoint with the extracted paymentId and securityKey.
  6. Check the response status. Consider the payment successful only if the status is "SUCCESS".

Installment Options

Endpoint: POST /api/installment-options

Description: Get available installment options for a card

Request Body:

{
  "amount": "number",
  "currency": "string",
  "pan": "string",
  "maxInstallmentCount": "number",
  "interestPaidByCustomer": "boolean"
}
        

Field Descriptions:

Field Description Example
amount Transaction amount 1000.00
currency Currency code TRY
pan Primary Account Number (card number) 5421190122090656
maxInstallmentCount Maximum number of installments to retrieve (optional) 12
interestPaidByCustomer Whether interest is paid by customer (optional) true

Response:

{
  "options": [
    {
      "installmentCount": 2,
      "installmentAmount": 510.00,
      "currency": "TRY",
      "interestAmount": 20.00,
      "totalAmount": 1020.00
    },
    {
      "installmentCount": 3,
      "installmentAmount": 345.00,
      "currency": "TRY",
      "interestAmount": 35.00,
      "totalAmount": 1035.00
    }
  ]
}
        

Response Field Descriptions:

Field Description Example
installmentCount Number of installments 3
installmentAmount Amount per installment 345.00
currency Currency code TRY
interestAmount Total interest amount 35.00
totalAmount Total amount to be paid 1035.00

Checkout

Description: Create a checkout link and process payment

1. Create Checkout Link

Endpoint: POST /api/checkout

Request Body:

{
  "orderId": "string",
  "amount": "number",
  "currency": "string",
  "description": "string",
  "callback": "string",
  "customerId": "string",
  "maxInstallmentCount": "number",
  "interestPaidByCustomer": "boolean"
}
        

Field Descriptions:

Field Description Example
orderId Client's tracking number for the order ORD-12345
amount Transaction amount 100.50
currency Currency code TRY
description Description of the checkout Product purchase
callback URL to be called after payment processing https://example.com/payment-callback
customerId Optional unique identifier for the customer CUST-12345
maxInstallmentCount Maximum number of installments allowed on the checkout page (optional, defaults to 1 — single payment). Installment options will be available based on the card type and merchant configuration. 6
interestPaidByCustomer Whether installment interest is paid by the customer (optional, defaults to false) true

Response:

{
  "checkoutId": "UUID",
  "redirectUrl": "string"
}
        

Response Field Descriptions:

Field Description Example
checkoutId Unique identifier for the checkout 123e4567-e89b-12d3-a456-426614174000
redirectUrl URL to redirect the user for payment https://api.example.com/checkout-link/123e4567-e89b-12d3-a456-426614174000

2. Redirect User

After receiving the response, redirect the user to the redirectUrl to complete the payment.

3. Callback Processing

After the payment is processed, the callback URL provided in the checkout creation request will be called with the checkoutId as form data.

4. Get Checkout Status

Endpoint: GET /api/checkout/{checkoutId}

Path Parameters:

Response:

Returns an ApiPaymentResponse object with payment details (same as Payment response).

Checkout Flow:

  1. Call the Create Checkout Link endpoint to generate a checkout link.
  2. Redirect the user to the received redirectUrl.
  3. Wait for the callback to be triggered after payment processing.
  4. When the callback is received, extract the checkoutId from the form data.
  5. Call the Get Checkout Status endpoint with the extracted checkoutId.
  6. Check the response status. Consider the payment successful only if the status is "SUCCESS".

Example Implementation:

// Create checkout link
const createCheckout = async (orderDetails) => {
  const response = await fetch('https://api.example.com/api/checkout', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-KEY': 'your_api_key_here',
      'X-API-SECRET': 'your_api_secret_here'
    },
    body: JSON.stringify(orderDetails)
  });
  const data = await response.json();
  return data.redirectUrl;
};

// Callback handler
app.post('/payment-callback', async (req, res) => {
  const checkoutId = req.body.checkoutId;
  const checkoutStatus = await getCheckoutStatus(checkoutId);
  
  if (checkoutStatus.status === 'SUCCESS') {
    // Process successful payment
    console.log('Payment successful');
  } else {
    // Handle failed payment
    console.log('Payment failed');
  }
  
  res.sendStatus(200);
});

// Get checkout status
const getCheckoutStatus = async (checkoutId) => {
  const response = await fetch(`https://api.example.com/api/checkout/${checkoutId}`, {
    method: 'GET',
    headers: {
      'X-API-KEY': 'your_api_key_here',
      'X-API-SECRET': 'your_api_secret_here'
    }
  });
  return await response.json();
};
        

Get Payment Status

Description: Query the current status of a payment by its ID. Use this endpoint to verify payment status independently — especially useful as a fallback when a webhook notification was not received.

Endpoint: GET /api/payment/{paymentId}

Path Parameters:

Response:

Returns an ApiPaymentResponse object. Same structure as payment responses.

When to use:

Example:

const getPaymentStatus = async (paymentId) => {
  const response = await fetch(`https://api.example.com/api/payment/${paymentId}`, {
    method: 'GET',
    headers: {
      'X-API-KEY': 'your_api_key_here',
      'X-API-SECRET': 'your_api_secret_here'
    }
  });
  return await response.json();
};

// 3DS fallback — kullanıcı callback'e yönlendirilmediyse
const paymentId = enrollmentResponse.paymentId; // POST /api/3ds'den dönen ID
const status = await getPaymentStatus(paymentId);

if (status.status === 'SUCCESS') {
  // Ödeme başarılı
} else if (status.status === 'FAILED' || status.status === 'CANCELLED') {
  // Ödeme başarısız
} else {
  // Hâlâ işleniyor (ENROLLED), biraz bekle ve tekrar sorgula
}
    

Cancel Payment

Description: Cancel a previously completed payment. A new payment record with transaction type CANCEL is created referencing the original payment.

Endpoint: POST /api/payment/{paymentId}/cancel

Request Body: None

Path Parameters:

Response:

Returns an ApiPaymentResponse for the newly created cancel transaction. Check status field — SUCCESS means the cancellation was accepted.

Important Notes:

Example:

const cancelPayment = async (paymentId) => {
  const response = await fetch(`https://api.example.com/api/payment/${paymentId}/cancel`, {
    method: 'POST',
    headers: {
      'X-API-KEY': 'your_api_key_here',
      'X-API-SECRET': 'your_api_secret_here'
    }
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(error.message);
  }

  const result = await response.json();
  if (result.status === 'SUCCESS') {
    console.log('Payment cancelled successfully');
  }
  return result;
};
    

Refund Payment

Description: Request a refund for a previously completed payment. Refund requests do not execute immediately — they are placed into an approval queue and processed after administrative approval.

Endpoint: POST /api/payment/{paymentId}/refund

Path Parameters:

Request Body:

{
  "amount": "50.00",
  "currency": "TRY"
}
    

Response:

Returns an ApiPaymentResponse with status: PENDING_APPROVAL. The response includes a new paymentId for the refund transaction.

Important Notes:

Refund Lifecycle:

  1. Send refund request → response status: PENDING_APPROVAL
  2. Administrative review and approval/rejection
  3. On approval: refund is executed at the bank → final status: SUCCESS or FAILED
  4. On rejection: final status: REJECTED
  5. Webhook notification sent with final status

Example:

const requestRefund = async (paymentId, amount, currency) => {
  const response = await fetch(`https://api.example.com/api/payment/${paymentId}/refund`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-KEY': 'your_api_key_here',
      'X-API-SECRET': 'your_api_secret_here'
    },
    body: JSON.stringify({ amount, currency })
  });

  const result = await response.json();
  // result.status === 'PENDING_APPROVAL'
  // result.paymentId → refund transaction ID (iade durumunu sorgulamak için)
  return result;
};

// Refund durumu sorgulama
const checkRefundStatus = async (refundPaymentId) => {
  const response = await fetch(`https://api.example.com/api/payment/${refundPaymentId}`, {
    method: 'GET',
    headers: {
      'X-API-KEY': 'your_api_key_here',
      'X-API-SECRET': 'your_api_secret_here'
    }
  });
  const result = await response.json();
  // result.status: PENDING_APPROVAL | SUCCESS | FAILED | REJECTED
  return result;
};
    

Webhooks

Description: Receive real-time notifications when payment status changes occur. Webhooks are sent as HTTP POST requests to your configured endpoint.

Overview

When a payment transitions to a final state (SUCCESS, FAILED, REJECTED, or CANCELLED), we send a webhook notification to your registered URL.

Setup

  1. Please contact our support team for webhook activation.
  2. Generate a Webhook Secret Key — this is used to verify the authenticity of incoming webhooks.
  3. Copy and securely store the secret key. It is shown only once.

Webhook Headers

Every webhook request includes two security headers:

Header Description Example
x-request-time Unix timestamp in milliseconds when the webhook was generated 1715150400000
x-request-signature HMAC SHA-256 hex digest of timestampMillis:payload 5d41402abc4b2a76b9719d911017c592...
x-event-id Unique identifier for the webhook event 123e4567-e89b-12d3-a456-426614174000
x-event-type Event type (e.g., payment.status_changed) payment.status_changed

Webhook Payload

Webhooks are sent as POST requests with a JSON body. The body is the ApiPaymentResponse object:

{
  "paymentId": "UUID",
  "orderId": "string",
  "amount": "number",
  "installmentCount": "number",
  "currency": "string",
  "merchantCommission": "number",
  "status": "string",
  "transactionType": "string",
  "paymentDate": "date",
  "cardHolderName": "string",
  "pan": "string",
  "domInt": "string",
  "cardScheme": "string",
  "cardType": "string",
  "cardSubType": "string",
  "loyaltyCode": "string",
  "externalTransactionId": "string",
  "authCode": "string",
  "resultCode": "string",
  "resultMessage": "string",
  "customerId": "string"
}
    

The payload is an exact representation of the ApiPaymentResponse object. Please refer to the Payment Response field descriptions for more details.

Signature Verification

You must verify the x-request-signature header to ensure the request is authentic and has not been tampered with.

Verification Steps:

  1. Extract the x-request-time header (epoch milliseconds).
  2. Extract the x-request-signature header (hex digest).
  3. Construct the signed content: x-request-time + ":" + raw_request_body
  4. Compute HMAC SHA-256 of the signed content using your webhook secret key.
  5. Compare the computed signature with the x-request-signature header value. If they match, the webhook is authentic.
  6. Recommended: Reject webhooks where the timestamp is older than 5 minutes to prevent replay attacks.

Verification Example (Node.js):

const crypto = require('crypto');

function verifyWebhook(requestBody, timestampHeader, signatureHeader, secret) {
  // 1. Construct signed content
  const signedContent = timestampHeader + ':' + requestBody;

  // 2. Compute expected signature
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(signedContent)
    .digest('hex');

  // 3. Compare signatures (timing-safe)
  const isValid = crypto.timingSafeEqual(
    Buffer.from(signatureHeader, 'hex'),
    Buffer.from(expectedSignature, 'hex')
  );

  // 4. Check timestamp freshness (5 minutes = 300000ms)
  const age = Date.now() - parseInt(timestampHeader);
  if (age > 300000) {
    return false; // Too old — possible replay attack
  }

  return isValid;
}

// Express.js webhook handler
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const timestamp = req.headers['x-request-time'];
  const signature = req.headers['x-request-signature'];
  const body = req.body.toString();

  if (!verifyWebhook(body, timestamp, signature, 'your_webhook_secret')) {
    return res.status(401).send('Invalid signature');
  }

  const event = JSON.parse(body);
  console.log('Payment status changed:', event.data.status);

  // Process the webhook...

  res.status(200).send('OK');
});
    

Verification Example (Java):

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.HexFormat;

public boolean verifySignature(String requestBody, String timestampHeader,
                                String signatureHeader, String secret) throws Exception {
    // 1. Construct signed content
    String signedContent = timestampHeader + ":" + requestBody;

    // 2. Compute expected signature
    Mac mac = Mac.getInstance("HmacSHA256");
    mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
    String expectedSignature = HexFormat.of().formatHex(
        mac.doFinal(signedContent.getBytes(StandardCharsets.UTF_8))
    );

    // 3. Compare signatures
    if (!expectedSignature.equals(signatureHeader)) {
        return false;
    }

    // 4. Check timestamp freshness (5 minutes = 300000ms)
    long age = System.currentTimeMillis() - Long.parseLong(timestampHeader);
    return age <= 300000;
}
    

Verification Example (Python):

import hmac
import hashlib
import time

def verify_webhook(request_body: str, timestamp_header: str,
                   signature_header: str, secret: str) -> bool:
    # 1. Construct signed content
    signed_content = f"{timestamp_header}:{request_body}"

    # 2. Compute expected signature
    expected_signature = hmac.new(
        secret.encode(), signed_content.encode(), hashlib.sha256
    ).hexdigest()

    # 3. Compare signatures (timing-safe)
    if not hmac.compare_digest(signature_header, expected_signature):
        return False

    # 4. Check timestamp freshness (5 minutes = 300000ms)
    age = int(time.time() * 1000) - int(timestamp_header)
    return age <= 300000
    

Retry Policy

The first delivery attempt is made immediately when the payment reaches a final state. If your endpoint does not respond with an HTTP 2xx status code, we will retry the webhook with exponential backoff:

Retry Delay After Failure Cumulative Time
1 30 seconds ~30s
2 1 minute ~1.5m
3 5 minutes ~6.5m
4 15 minutes ~21.5m
5 1 hour ~1.4h
6 4 hours ~5.4h
7 12 hours ~17.4h
8+ 24 hours ~41.4h

Retries will continue for up to 48 hours after the initial event. After this period, the webhook is permanently marked as failed.

Best Practices