Çekim API'si
Merchant bakiyenizden herhangi bir blockchain adresine çekim gönderin.
Çekim API'si, merchant bakiyenizden herhangi bir blockchain adresine programatik olarak para çekmenize olanak tanır.
Tüm Çekim endpoint'leri için sign imzasını üretmek üzere ayrı bir Payout API key kullanmalısınız. Bu anahtar normal API key'inizden farklıdır ve proje ayarlarınızda oluşturulmalıdır.
Çekim oluştur
Merchant bakiyenizden bir çekim isteği oluşturur.
/v1/payoutİstek parametreleri
| Alan | Tip | Gerekli | Açıklama |
|---|---|---|---|
currency | string | evet | Çekim para birimi (bkz. References) |
network | string | evet | Ağ kodu (bkz. References) |
amount | string | evet | Çekim tutarı |
to_address | string | evet | Alıcı blockchain adresi |
order_id | string | hayır | Idempotency anahtarı — proje içinde benzersiz. Aynı order_id ile yapılan tekrar POST yeni bir çekim oluşturmaz — onun yerine mevcut olan döner |
url_callback | string | hayır | Çekim webhook'ları için URL. Bu çekim için webhook'ları devre dışı bırakmak için boş bırakın |
memo | string | null | hayır | Hedef etiketi / memo. Şu anda yalnızca TON ve SOL ağları tarafından kullanılır; en fazla 255 karakter |
from_currency | string | hayır | Çekim anında düşülerek otomatik olarak currency'ye dönüştürülen kaynak bakiye. Bakiyenizi USDT gibi bir stabilcoinde tutarken volatil varlıklarla (BTC, ETH, …) çekim yapmanıza olanak tanır — volatil kriptoyu kendiniz tutmak zorunda kalmazsınız. USDT bakiyesinden düşmek için "USDT" geçirin |
fee_option | string | hayır | Ücretlerin nasıl tahsil edileceği. deduct (varsayılan) — ağ + platform ücretleri amount'tan düşülür, alıcı amount - fees alır. add — ücretler üste eklenir, merchant'tan amount + fees düşülür, alıcı tam olarak amount alır |
Idempotency. Bir proje içinde, çekim order_id ile benzersizdir. Aynı order_id ile aynı POST isteğini yeniden göndermek güvenlidir — API, bir kopya oluşturmak yerine mevcut çekimi döner. Production çekimleri için her zaman bir order_id geçirin.
İstek örnekleri
curl -X POST https://api.2328.io/api/v1/payout \
-H "Content-Type: application/json" \
-H "User-Agent: MyShop/1.0 (+https://myshop.example)" \
-H "project: YOUR_PROJECT_UUID" \
-H "sign: YOUR_HMAC_SIGNATURE" \
-d '{"currency":"TRX","network":"TRX-TRC20","amount":"1.00","to_address":"TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t","order_id":"9ed25264-8be4-439f-acf5-2a8732538d27","url_callback":"https://your-site.com/webhook/payout","memo":null,"fee_option":"deduct"}'<?php
function apiSign(string $body, string $apiKey): string {
return hash_hmac('sha256', base64_encode($body), $apiKey);
}
$project = 'YOUR_PROJECT_UUID';
$apiKey = 'YOUR_PAYOUT_API_KEY';
$data = [
'currency' => 'TRX',
'network' => 'TRX-TRC20',
'amount' => '1.00',
'to_address' => 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t',
'order_id' => '9ed25264-8be4-439f-acf5-2a8732538d27',
'url_callback' => 'https://your-site.com/webhook/payout',
'memo' => null,
'fee_option' => 'deduct',
];
$body = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
$sign = apiSign($body, $apiKey);
$ch = curl_init('https://api.2328.io/api/v1/payout');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $body,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'User-Agent: MyShop/1.0 (+https://myshop.example)',
"project: $project",
"sign: $sign",
],
]);
$response = json_decode(curl_exec($ch), true);import { createHmac } from "crypto";
function apiSign(body, apiKey) {
const base64 = Buffer.from(body, "utf8").toString("base64");
return createHmac("sha256", apiKey).update(base64).digest("hex");
}
const PROJECT_UUID = "YOUR_PROJECT_UUID";
const PAYOUT_API_KEY = process.env.PAYOUT_API_KEY;
const data = {
currency: "TRX",
network: "TRX-TRC20",
amount: "1.00",
to_address: "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
order_id: "9ed25264-8be4-439f-acf5-2a8732538d27",
url_callback: "https://your-site.com/webhook/payout",
memo: null,
fee_option: "deduct",
};
const body = JSON.stringify(data);
const sign = apiSign(body, PAYOUT_API_KEY);
const res = await fetch("https://api.2328.io/api/v1/payout", {
method: "POST",
headers: {
"Content-Type": "application/json",
"User-Agent": "MyShop/1.0 (+https://myshop.example)",
project: PROJECT_UUID,
sign,
},
body,
});
const json = await res.json();import json
import hmac
import hashlib
import base64
import httpx
def api_sign(body: str, api_key: str) -> str:
b64 = base64.b64encode(body.encode("utf-8")).decode()
return hmac.new(api_key.encode(), b64.encode(), hashlib.sha256).hexdigest()
PROJECT_UUID = "YOUR_PROJECT_UUID"
PAYOUT_API_KEY = "YOUR_PAYOUT_API_KEY"
data = {
"currency": "TRX",
"network": "TRX-TRC20",
"amount": "1.00",
"to_address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
"order_id": "9ed25264-8be4-439f-acf5-2a8732538d27",
"url_callback": "https://your-site.com/webhook/payout",
"memo": None,
"fee_option": "deduct",
}
body = json.dumps(data, separators=(",", ":"), ensure_ascii=False)
sign = api_sign(body, PAYOUT_API_KEY)
r = httpx.post(
"https://api.2328.io/api/v1/payout",
headers={
"Content-Type": "application/json",
"User-Agent": "MyShop/1.0 (+https://myshop.example)",
"project": PROJECT_UUID,
"sign": sign,
},
content=body.encode("utf-8"),
)
response = r.json()package main
import (
"bytes"
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"encoding/json"
"net/http"
)
func apiSign(body []byte, apiKey string) string {
b64 := base64.StdEncoding.EncodeToString(body)
h := hmac.New(sha256.New, []byte(apiKey))
h.Write([]byte(b64))
return hex.EncodeToString(h.Sum(nil))
}
func marshalCanonical(v any) ([]byte, error) {
var buf bytes.Buffer
enc := json.NewEncoder(&buf)
enc.SetEscapeHTML(false)
if err := enc.Encode(v); err != nil {
return nil, err
}
return bytes.TrimRight(buf.Bytes(), "\n"), nil
}
type CreatePayout struct {
Currency string `json:"currency"`
Network string `json:"network"`
Amount string `json:"amount"`
ToAddress string `json:"to_address"`
OrderID string `json:"order_id"`
URLCallback string `json:"url_callback"`
Memo *string `json:"memo"`
FeeOption string `json:"fee_option"`
}
func main() {
const projectUUID = "YOUR_PROJECT_UUID"
const payoutAPIKey = "YOUR_PAYOUT_API_KEY"
data := CreatePayout{
Currency: "TRX",
Network: "TRX-TRC20",
Amount: "1.00",
ToAddress: "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
OrderID: "9ed25264-8be4-439f-acf5-2a8732538d27",
URLCallback: "https://your-site.com/webhook/payout",
Memo: nil,
FeeOption: "deduct",
}
body, err := marshalCanonical(data)
if err != nil {
panic(err)
}
sign := apiSign(body, payoutAPIKey)
req, _ := http.NewRequest("POST",
"https://api.2328.io/api/v1/payout",
bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("User-Agent", "MyShop/1.0 (+https://myshop.example)")
req.Header.Set("project", projectUUID)
req.Header.Set("sign", sign)
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}Yanıt örneği
{
"state": 0,
"result": {
"uuid": "019dea62-1727-72aa-ac2c-eaf2ade193ef",
"order_id": "9ed25264-8be4-439f-acf5-2a8732538d27",
"status": "pending",
"currency": "TRX",
"network": "TRX-TRC20",
"amount": "1.00",
"merchant_amount": "1",
"network_amount": "0.89",
"amount_usd": "0.33",
"to_address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
"memo": null,
"txid": null,
"block_number": null,
"error_type": null,
"created_at": "2026-05-02T23:29:50+03:00",
"updated_at": "2026-05-02T23:29:50+03:00"
}
}Ücretler. Varsayılan fee_option: deduct — ağ + platform ücretleri amount'tan düşülür (alıcı amount - fees alır). Ücretleri üste eklemek için fee_option: add geçirin — alıcı tam olarak amount alır ve merchant'tan amount + fees düşülür.
Çekim hesaplama
Çekim tutarlarını ve ücretlerini çekim oluşturmadan ve bakiyenizden düşmeden tahmin eder. Kullanıcıya onaydan önce alacağı (veya ödeyeceği) tutarı tam olarak göstermek için kullanın.
/v1/payout/calcİstek parametreleri
Çekim oluştur ile aynıdır — aynı alanlar, aynı imza. order_id, url_callback, to_address ve memo alanları kabul edilir ancak yok sayılır: hiçbir çekim kaydı oluşmaz ve callback gönderilmez.
İstek örneği
curl -X POST https://api.2328.io/api/v1/payout/calc \
-H "Content-Type: application/json" \
-H "User-Agent: MyShop/1.0 (+https://myshop.example)" \
-H "project: YOUR_PROJECT_UUID" \
-H "sign: YOUR_HMAC_SIGNATURE" \
-d '{"currency":"USDT","network":"TRX-TRC20","amount":"100","fee_option":"add"}'Yanıt örneği
{
"state": 0,
"result": {
"currency": "USDT",
"network": "TRX-TRC20",
"amount": "100",
"fee_option": "add",
"merchant_amount": "103.00000000",
"network_amount": "100",
"total_fee": "3.00000000",
"total_fee_usd": "3.00000000"
}
}Yalnızca önizleme. Bu endpoint salt okunurdur — hiçbir bakiye düşülmez ve çekim kaydı oluşturulmaz. Arayüzünüzde ücret dökümünü göstermek için ihtiyaç duydukça çağırabilirsiniz.
Çekim durumu
Bir çekim isteğinin durumunu alın.
/v1/payout/status/{uuid}Path parametreleri
| Alan | Tip | Gerekli | Açıklama |
|---|---|---|---|
uuid | string | evet | Çekim UUID (oluşturmadaki result.uuid'den) |
Yanıt örneği
{
"state": 0,
"result": {
"uuid": "019dff1f-0dbd-7277-8d45-271e7775388f",
"order_id": "4dfdcc84402b1185b71cbe399321533e",
"status": "completed",
"currency": "TRX",
"network": "TRX-TRC20",
"amount": "3.00",
"merchant_amount": "3.00",
"network_amount": "3.00",
"amount_usd": "1.04",
"to_address": "THauRv5tcucQRohXg8NiyGTk16DX1XQG5x",
"memo": null,
"txid": "9242e533703704ef3eaba840f70b4a26333e72c943377ee375fea17badb53def",
"block_number": null,
"error_type": null,
"created_at": "2026-05-07T00:08:38+03:00",
"updated_at": "2026-05-07T00:08:54+03:00",
"from_currency": "USDT",
"debited_amount": "1.050735",
"debited_currency": "USDT"
}
}Bu GET isteği için imza boş bir gövdeden hesaplanır:
hash_hmac('sha256', base64_encode(''), $apiKey)
Yanıt alanları
POST /v1/payout ve GET /v1/payout/status/{uuid} çağrılarının result alanında dönen alanlar:
| Alan | Tip | Açıklama |
|---|---|---|
uuid | string | Sistem tarafından atanan çekim UUID'si |
order_id | string | Dahili çekim tanımlayıcınız (proje içinde benzersiz) |
status | string | Mevcut çekim durumu (aşağıya bakın) |
currency | string | Çekim para birimi |
network | string | Ağ kodu |
amount | string | Talep edildiği şekliyle çekim tutarı |
merchant_amount | string | Merchant bakiyesinden düşülen tutar |
network_amount | string | Zincir üzerinde gerçekten gönderilen tutar (ağ + platform ücretlerinden sonra) |
amount_usd | string | Çekim tutarının USD karşılığı |
to_address | string | Alıcı blockchain adresi |
memo | string | null | Hedef etiketi / memo (TON, SOL). Aksi halde null |
txid | string | null | Blockchain işlem hash'i. İşlem gönderilene kadar null |
block_number | int | null | İşlemin dahil edildiği blok numarası. Dahil edilene kadar null |
error_type | string | null | status = failed olduğunda hata nedeni (aşağıdaki Hata türlerine bakın). Aksi halde null |
created_at | string (ISO 8601) | Çekim oluşturma zamanı |
updated_at | string (ISO 8601) | Son durum değişikliği zamanı |
from_currency | string | null | Otomatik dönüştürme kullanıldığında çekimin düşüldüğü kaynak bakiye (örn. BTC çekimi için USDT). Dönüştürme yapılmadıysa null |
debited_amount | string | null | Dönüştürmeden sonra kaynak bakiyeden gerçekten düşülen tutar. Yalnızca otomatik dönüştürme kullanıldığında mevcuttur |
debited_currency | string | null | debited_amount'un para birimi — fonların düşüldüğü bakiye |
Çekim durumları
status alanı aşağıdaki değerleri alabilir:
| Durum | Açıklama |
|---|---|
pending | Oluşturuldu, işlenmeyi bekliyor |
completed | Başarıyla tamamlandı — txid ayarlandı |
failed | Gönderim hatası — bkz. error_type |
cancelled | İptal edildi |
Hata türleri
status = failed olduğunda error_type alanı nedeni açıklar:
| Kod | Açıklama |
|---|---|
aml_risk | Çekim AML risk kontrolleri tarafından engellendi (alıcı adres yüksek riskli olarak işaretlendi) |
Webhook bildirimleri
Bir çekimin durumu değiştiğinde, sistem çekim oluşturulurken geçirilen url_callback URL'ine bir POST webhook gönderir. url_callback sağlanmadıysa, o çekim için webhook gönderilmez.
- Method:
POST - Content-Type:
application/json - İmza: istek gövdesindeki
signalanı, Payout API key ile hesaplanır (çekim isteklerini imzalamak için kullanılan aynı anahtar).
Payload, GET /v1/payout/status/{uuid} çağrısının result nesnesini ve doğrulama için bir sign alanını yansıtır.
Payload
{
"uuid": "019dff1f-0dbd-7277-8d45-271e7775388f",
"order_id": "4dfdcc84402b1185b71cbe399321533e",
"status": "completed",
"currency": "TRX",
"network": "TRX-TRC20",
"amount": "3.00",
"merchant_amount": "3.00",
"network_amount": "3.00",
"amount_usd": "1.04",
"to_address": "THauRv5tcucQRohXg8NiyGTk16DX1XQG5x",
"memo": null,
"txid": "9242e533703704ef3eaba840f70b4a26333e72c943377ee375fea17badb53def",
"block_number": null,
"error_type": null,
"created_at": "2026-05-07T00:08:38+03:00",
"updated_at": "2026-05-07T00:08:54+03:00",
"from_currency": "USDT",
"debited_amount": "1.050735",
"debited_currency": "USDT",
"sign": "925ad7bf3d6841864101f7cc2c7e30652e70a06cdb04dbe07a0129480000ce4a"
}İmzayı doğrulama. Ödeme webhook'larıyla aynı algoritmayı kullanın, ancak normal API key yerine Payout API key ile imzalayın. sign alanını çıkarın, kalan payload'u JSON'a encode edin, Base64 ile encode edin, ardından hash_hmac('sha256', $base64, $payoutApiKey) hesaplayın ve alınan sign ile karşılaştırın.