İçeriğe atlayın

API

Bu sayfada

Oluştur

Kendi harici kimliğinize bağlı, desteklenen her ağda tek kalıcı adresi olan, yeniden kullanılabilir bir yatırma kimliği oluşturun.

POST/v1/payment-channels

API anahtarı: Payment

Ödeme kanalı, tek bir müşteriniz için kalıcı bir yatırma kimliğidir. Faturadan farklı olarak tutarı, süre sonu ve nihai durumu yoktur: bir kez oluşturur, adreslerini gösterirsiniz; sonra gelen her transfer, bakiyenize geçen bir yatırmaya dönüşür.

İstek gövdesi

Parametre Tip Zorunlu Açıklama
project_id string Evet Önekli proje kimliği (prj_…). Kanalın hangi token'ları kabul edeceğine proje karar verir.
external_id string Evet Müşteri için kendi kalıcı kimliğiniz, en fazla 128 karakter. Kanal oluştuktan sonra değiştirilemez.
{
  "project_id": "prj_xFukZuAJZR06pLVBh3uwzv",
  "external_id": "customer-42"
}

Idempotency

İmzaladığınız API anahtarının ortamı içinde project_id + external_id çifti, idempotency anahtarının kendisidir. Gönderilecek başka bir şey yoktur; dolayısıyla tekrar çağrıda çözülecek bir yük çakışması da yoktur.

  • İlk çağrı → yeni kanalı gösteren bir Location başlığıyla 201 Created.
  • Aynı çiftle yapılan sonraki her çağrı → aynı kanalla 200 OK. Kopya oluşmaz.
  • Sandbox'taki ve production'daki aynı external_id, birbirinden bağımsız iki kanaldır.

Kendi sisteminizde zaten kullandığınız müşteri kimliğini gönderin ve pc_ kimliğini kendiniz saklamak yerine bu uç noktayı her ödemede çağırın. Tekrar çağrı ne hatadır ne de kopya: iki durum kodu da bir kanal döndürür ve 200, kanalın bugün sahip olduğu adresleri ve token'ları taşır. Zaman aşımına uğrayan bir isteği yeniden denediğinizde ikinci bir kanal açılmaz, ilk kanal döner.

Kod örnekleri

Her sekme, o dilin resmî SDK'sını kullanır. İmzalama, serileştirme, güvenli yeniden denemeler ve tiplenmiş hatalar SDK tarafından yönetilir.

API_KEY_ID="pk_live_xxxxxxxxxxxx"
API_SECRET="sk_live_xxxxxxxxxxxx"
BODY='{"project_id":"prj_xxxxxxxxxxxx","external_id":"customer-42"}'

TS=$(date +%s)
BODY_HASH=$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | sed 's/^.* //')
SIGNATURE=$(printf '%s\n%s\n%s\n%s\n%s' "$TS" POST /v1/payment-channels '' "$BODY_HASH" \
  | openssl dgst -sha256 -hmac "$API_SECRET" -binary | base64)

curl -sS https://api.paymos.io/v1/payment-channels \
  -H "Authorization: HMAC-SHA256 $API_KEY_ID:$SIGNATURE" \
  -H "X-Request-Timestamp: $TS" \
  -H "Content-Type: application/json" \
  -d "$BODY"
import { Paymos } from '@paymos/sdk';

const paymos = new Paymos({
  apiKey: process.env.PAYMOS_API_KEY,
  apiSecret: process.env.PAYMOS_API_SECRET,
});

const channel = await paymos.paymentChannels.create({
  projectId: 'prj_xxxxxxxxxxxx',
  externalId: 'customer-42',
});

for (const rail of channel.networks) {
  console.log(rail.network, rail.address ?? rail.status);
}
import os

from paymos import Paymos

paymos = Paymos(
    api_key=os.environ["PAYMOS_API_KEY"],
    api_secret=os.environ["PAYMOS_API_SECRET"],
)
channel = paymos.payment_channels.create(
    project_id="prj_xxxxxxxxxxxx",
    external_id="customer-42",
)

for rail in channel["networks"]:
    print(rail["network"], rail.get("address", rail["status"]))
<?php
use Paymos\Client;
use Paymos\ClientConfig;

$paymos = new Client(new ClientConfig(
    getenv('PAYMOS_API_KEY'),
    getenv('PAYMOS_API_SECRET')
));
$channel = $paymos->paymentChannels()->create(array(
    'project_id' => 'prj_xxxxxxxxxxxx',
    'external_id' => 'customer-42',
));

foreach ($channel['networks'] as $rail) {
    $address = isset($rail['address']) ? $rail['address'] : $rail['status'];
    echo $rail['network'] . ' ' . $address . PHP_EOL;
}
package main

import (
	"context"
	"fmt"
	"os"

	paymos "github.com/Paymos-labs/go-sdk/v2"
)

func main() {
	client, err := paymos.NewClient(os.Getenv("PAYMOS_API_KEY"), os.Getenv("PAYMOS_API_SECRET"))
	if err != nil {
		panic(err)
	}
	channel, err := client.PaymentChannels.Create(context.Background(), paymos.CreatePaymentChannelParams{
		ProjectID:  "prj_xxxxxxxxxxxx",
		ExternalID: "customer-42",
	})
	if err != nil {
		panic(err)
	}
	for _, rail := range channel.Networks {
		fmt.Println(rail.Network, addressOrStatus(rail))
	}
}

func addressOrStatus(rail paymos.PaymentChannelNetwork) string {
	if rail.Address == nil {
		return string(rail.Status)
	}
	return *rail.Address
}
using Paymos;

using var paymos = new PaymosClient(
    Environment.GetEnvironmentVariable("PAYMOS_API_KEY")!,
    Environment.GetEnvironmentVariable("PAYMOS_API_SECRET")!);

var channel = await paymos.PaymentChannels.CreateAsync(new CreatePaymentChannelRequest(
    ProjectId: "prj_xxxxxxxxxxxx",
    ExternalId: "customer-42"));

foreach (var rail in channel.Networks)
{
    Console.WriteLine($"{rail.Network} {rail.Address ?? rail.Status}");
}
import io.paymos.CreatePaymentChannelRequest;
import io.paymos.PaymentChannel;
import io.paymos.PaymentChannelNetwork;
import io.paymos.PaymosClient;

PaymosClient paymos = new PaymosClient(
    System.getenv("PAYMOS_API_KEY"),
    System.getenv("PAYMOS_API_SECRET"));

PaymentChannel channel = paymos.paymentChannels.create(
    new CreatePaymentChannelRequest("prj_xxxxxxxxxxxx", "customer-42"));

for (PaymentChannelNetwork rail : channel.networks()) {
    System.out.println(rail.network() + " "
        + (rail.address() == null ? rail.status() : rail.address()));
}
require 'paymos'

paymos = Paymos::Client.new(
  api_key: ENV.fetch('PAYMOS_API_KEY'),
  api_secret: ENV.fetch('PAYMOS_API_SECRET')
)
channel = paymos.payment_channels.create(
  project_id: 'prj_xxxxxxxxxxxx',
  external_id: 'customer-42'
)

channel.networks.each do |rail|
  puts "#{rail.network} #{rail.address || rail.status}"
end
use paymos::{CreatePaymentChannelRequest, PaymosClient};

let paymos = PaymosClient::new(
    std::env::var("PAYMOS_API_KEY")?,
    std::env::var("PAYMOS_API_SECRET")?,
)?;
let channel = paymos
    .payment_channels()
    .create(&CreatePaymentChannelRequest {
        project_id: "prj_xxxxxxxxxxxx".to_owned(),
        external_id: "customer-42".to_owned(),
    })
    .await?;

for rail in &channel.networks {
    println!("{} {}", rail.network, rail.address.as_deref().unwrap_or(&rail.status));
}

Yanıt (201 Created, tekrarda 200)

{
  "id": "pc_2QhKZv6mRt9WdA3nYpLbXf",
  "project_id": "prj_xFukZuAJZR06pLVBh3uwzv",
  "external_id": "customer-42",
  "status": "active",
  "is_accepting_payments": true,
  "is_fully_provisioned": false,
  "is_test": false,
  "applied_fee_percent": 1.0,
  "customer_fee_percent": 0,
  "networks": [
    {
      "network": "TRC20",
      "status": "active",
      "address": "TN3W4H6rK2ce4vX9YnFQHwKENnHjoxb3m9",
      "tokens": [
        { "symbol": "USDT", "minimum_deposit": "1.00" },
        { "symbol": "USDC", "minimum_deposit": "1.00" }
      ]
    },
    {
      "network": "ERC20",
      "status": "active",
      "address": "0x9f2a6c1b4e8d7350ab11c9e5f0d2743b86ce41d9",
      "tokens": [
        { "symbol": "USDT", "minimum_deposit": "12.00" },
        { "symbol": "USDC", "minimum_deposit": "12.00" }
      ]
    },
    {
      "network": "SOL",
      "status": "provisioning",
      "tokens": [
        { "symbol": "USDC", "minimum_deposit": null }
      ]
    }
  ],
  "created_at": 1767225600,
  "updated_at": 1767225780
}

Ağlar ve adresler

Kanalın kendine ait bir token listesi yoktur. Projenin kabul ettiğini kabul eder: projede bir token'ı etkinleştirmek onu o projenin her kanalına ekler, kapatmak ise her yerden kaldırır. Kabul edilen kümeyi Panel → Projeler üzerinden yönetin.

networks dizisindeki her kayıt tek bir zinciri anlatır:

Alan Anlamı
network Ağ kodu, örneğin TRC20 veya ERC20.
status Adres oluştuğunda active, o ana kadar provisioning.
address Kalıcı yatırma adresi. O ağın hazırlığı bitene kadar bulunmaz: henüz yok demektir, hiç olmayacak değil. Bir kez döndükten sonra bir daha değişmez.
tokens O ağın şu anda kabul ettikleri. Her kayıt bir nesnedir: symbol ve minimum_deposit; yalın bir token kodu değil.

Müşteriye ne göstereceğinizi iki kural belirler:

  • Yalnızca tokens dizisi boş olmayan active ağları gösterin. provisioning durumundaki bir kaydın henüz gösterilecek adresi yoktur.
  • API'nin artık döndürmediği bir rotayı göstermeyi bırakın. Adresler asla yeniden atanmaz; ancak projeden kaldırdığınız bir ağ yanıttan çıkar ve oraya gönderilen para artık beklenmez.

Döndürülen adres, o kanalda kalıcıdır. Önbelleğe alın: kanalı yeniden okuduğunuzda aynı değer gelir ve aynı adres, o ağdaki her token'ı karşılar.

Listedeki her token'ın kendi minimum_deposit değeri vardır: o rotada hesaba geçen en küçük transfer. Değeri, gösterdiğiniz yanıttan alın ve adresin yanında belirtin. Alanın tamamı, null durumu dahil, Ödeme Kanalı Getir sayfasında anlatılıyor.

Adres hazırlığı

Yeni bir production kanalı adressiz, provisioning durumunda açılır. Her ağ bağımsız hazırlanır ve kendi adresi oluştuğu anda kullanılabilir olur — son zinciri beklemeniz gerekmez. Kanal, ilk hazır adreste active durumuna geçer ve orada kalır.

is_fully_provisioned, gereken her ağın hazır olup olmadığını söyler. Bir kanal active olup henüz tam hazır olmayabilir; kalan zincirler yetişirken normal durum budur.

Sandbox kanalları anında hazırdır: adresleri yerel olarak türetilir ve hiçbir zincire dokunmaz.

Komisyonlar

applied_fee_percent ve customer_fee_percent, güncel oranlarınızdır. Referans olarak gösterilir, bir teklif değildir — fiyatlandırmanız değiştiğinde onlar da değişir.

Bağlayıcı sayılar her yatırmanın üzerindedir. Her yatırma, kanala işlendiği andaki oranları kaydeder ve kendi gross, fee ve net değerlerini bildirir. Fiyatlandırma değişikliği, hâlihazırda aldığınız bir ödemeyi yeniden yazmaz. Komisyon önizleme uç noktası yoktur: aritmetiği görmek isterseniz sandbox'ta bir yatırma oluşturun.

Hatalar

Kod HTTP Ne zaman
payment_channels_disabled 503 Ödeme kanalları, bu ortamda hesabınız için etkin değil.
payment_key_required 403 İstek, Payout (rk_) anahtarıyla imzalandı.
project_not_found 404 project_id, bu kimlik bilgisinin görebildiği hiçbir şeye çözülmüyor.
payment_channel_external_id_invalid 400 external_id boş, yalnızca boşluk veya 128 karakterden uzun.
payment_channel_project_has_no_supported_tokens 409 Proje, bir kanalın tahsil edebileceği hiçbir token'ı etkinleştirmiyor.

Tam katalog için bkz. Hata Kodları.

Bu API'de olmayanlar

Güncelleme, silme, yeniden atama, callback URL'si, kanal başına token veya komisyon önizleme uç noktası yoktur. Kanalın kimliği tasarım gereği değişmez: bir müşterinin kaydettiği adres, sonradan başka birinin adresi hâline gelemez. Bir kanalı kullanımdan kaldırmak için engelleyin.