İçeriğe atlayın

API

Bu sayfada

Yatırma akışı

Onaylanmış kanal yatırmalarını yayın sırasıyla, hep ilerleyen bir imleçle sorgulayın; kesinleşmiş hiçbir ödeme atlanmaz veya sessizce tekrarlanmaz.

GET/v1/payment-channel-deposits

API anahtarı: Payment

Bu bir entegrasyon akışıdır, geçmiş sayfası değil. Yalnızca onaylanmış yatırmaları, en eskiden başlayarak, genel bir yayın sırasıyla döndürür ve her zaman bir imleç verir. Belirli aralıklarla sorgularsanız kesinleşmiş her ödemeyi tam olarak bir kez ve sonradan bozulmayan bir sırayla görürsünüz.

Webhook'lar hızlı yoldur; bu akış ise güvenilir yol. İkisini birlikte çalıştırın: webhook'lar size saniyeleri kazandırır, akış ise uç noktanız kapalı kalmış olsa bile her şeyi eninde sonunda gördüğünüzü garanti eder.

Sorgu parametreleri

Parametre Tip Varsayılan Açıklama
limit integer 20 1 ile 100 arasında sayfa boyutu.
cursor string Bir önceki sayfanın next_cursor değerinden gelen opak imleç.
project_id string Tek bir projeyle sınırlar (prj_…).
payment_channel_id string Tek bir kanalla sınırlar (pc_…).
confirmed_from integer Unix saniye; yalnızca bu andan itibaren onaylanmış yatırmalar. Yalnızca ilk sorguyu sınırlar — aşağıya bakın.

status parametresi bilinçli olarak yoktur. confirming sorgulayabilen bir istemci, bir reorg'un hâlâ geri alabileceği parayı kesinleşmiş saymış olurdu.

Örnek

GET /v1/payment-channel-deposits?limit=100&cursor=CfDJ8JvN… HTTP/1.1
Host: api.paymos.io
Authorization: HMAC-SHA256 pk_live_…:…
X-Request-Timestamp: 1767225660

Kod örnekleri

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

API_KEY_ID="pk_live_xxxxxxxxxxxx"
API_SECRET="sk_live_xxxxxxxxxxxx"
QUERY="?limit=100"

TS=$(date +%s)
# No body: the hash slot is the EMPTY STRING, not sha256("") — its fixed
# e3b0c442… digest signs a different payload and the request is rejected. The
# query keeps its leading "?" exactly as transmitted.
SIGNATURE=$(printf '%s\n%s\n%s\n%s\n%s' "$TS" GET /v1/payment-channel-deposits "$QUERY" '' \
  | openssl dgst -sha256 -hmac "$API_SECRET" -binary | base64)

curl -sS "https://api.paymos.io/v1/payment-channel-deposits$QUERY" \
  -H "Authorization: HMAC-SHA256 $API_KEY_ID:$SIGNATURE" \
  -H "X-Request-Timestamp: $TS"
import { Paymos } from '@paymos/sdk';

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

const page = await paymos.paymentChannelDeposits.read({ limit: 100 });

for (const deposit of page.items) {
  console.log(deposit.id, deposit.net, deposit.currency);
}

console.log('resume from', page.nextCursor);
import os

from paymos import Paymos

paymos = Paymos(
    api_key=os.environ["PAYMOS_API_KEY"],
    api_secret=os.environ["PAYMOS_API_SECRET"],
)

page = paymos.payment_channel_deposits.read(limit=100)

for deposit in page["items"]:
    print(deposit["id"], deposit["net"], deposit["currency"])

print("resume from", page["next_cursor"])
<?php
use Paymos\Client;
use Paymos\ClientConfig;

$paymos = new Client(new ClientConfig(
    getenv('PAYMOS_API_KEY'),
    getenv('PAYMOS_API_SECRET')
));

$page = $paymos->paymentChannelDeposits()->readPage(array('limit' => 100));

foreach ($page['items'] as $deposit) {
    echo $deposit['id'] . ' ' . $deposit['net'] . ' ' . $deposit['currency'] . PHP_EOL;
}

echo 'resume from ' . $page['next_cursor'] . 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)
	}

	page, err := client.PaymentChannelDeposits.Read(context.Background(), paymos.PaymentChannelDepositFeedParams{
		Limit: 100,
	})
	if err != nil {
		panic(err)
	}
	for _, deposit := range page.Items {
		fmt.Println(deposit.ID, deposit.Net, deposit.Currency)
	}
	fmt.Println("resume from", page.NextCursor)
}
using Paymos;

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

var page = await paymos.PaymentChannelDeposits.ReadAsync(
    new PaymentChannelDepositFeedOptions(Limit: 100));

foreach (var deposit in page.Items)
{
    Console.WriteLine($"{deposit.Id} {deposit.Net} {deposit.Currency}");
}

Console.WriteLine($"resume from {page.NextCursor}");
import io.paymos.PaymentChannelDeposit;
import io.paymos.PaymentChannelDepositFeedOptions;
import io.paymos.PaymentChannelDepositFeedPage;
import io.paymos.PaymosClient;

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

PaymentChannelDepositFeedPage page = paymos.paymentChannelDeposits.read(
    PaymentChannelDepositFeedOptions.builder().limit(100).build());

for (PaymentChannelDeposit deposit : page.items()) {
    System.out.println(deposit.id() + " " + deposit.net() + " " + deposit.currency());
}

System.out.println("resume from " + page.nextCursor());
require 'paymos'

paymos = Paymos::Client.new(
  api_key: ENV.fetch('PAYMOS_API_KEY'),
  api_secret: ENV.fetch('PAYMOS_API_SECRET')
)

page = paymos.payment_channel_deposits.read(limit: 100)

page.items.each do |deposit|
  puts "#{deposit.id} #{deposit.net} #{deposit.currency}"
end

puts "resume from #{page.next_cursor}"
use paymos::{PaymentChannelDepositFeedParams, PaymosClient};

let paymos = PaymosClient::new(
    std::env::var("PAYMOS_API_KEY")?,
    std::env::var("PAYMOS_API_SECRET")?,
)?;

let page = paymos
    .payment_channel_deposits()
    .read(&PaymentChannelDepositFeedParams {
        limit: Some(100),
        ..Default::default()
    })
    .await?;

for deposit in &page.items {
    println!("{} {} {}", deposit.id, deposit.net, deposit.currency);
}

println!("resume from {}", page.next_cursor);

Yanıt (200 OK)

{
  "items": [
    {
      "id": "pcd_8ScRvL4jNq2XkB7mTfZdWu",
      "payment_channel_id": "pc_2QhKZv6mRt9WdA3nYpLbXf",
      "project_id": "prj_xFukZuAJZR06pLVBh3uwzv",
      "payment_channel_external_id": "customer-42",
      "status": "confirmed",
      "is_final": true,
      "is_test": false,
      "currency": "USDT",
      "network": "TRC20",
      "chain_id": 728126428,
      "contract_address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
      "gross": "100",
      "fee": "1",
      "net": "99",
      "applied_fee_percent": 1.0,
      "customer_fee_percent": 0,
      "tx_hash": "9f4c1b7e30ad52c8ef6a1d84b0c39f27a5e6d138f4b90c72ae51d63b8407fc25",
      "transfer_id": "9f4c1b7e30ad52c8ef6a1d84b0c39f27a5e6d138f4b90c72ae51d63b8407fc25:41a614f803b6fd780986a42c78ec9c7f77e6ded13c:41c9f6a2b7d0138e54ca3b91f6072ed48a5c1e93b7:0",
      "source_address": "TW9s4RkAqBnLpVdX2ChYzUeGm7QfKt3NbZ",
      "destination_address": "TN3W4H6rK2ce4vX9YnFQHwKENnHjoxb3m9",
      "block_height": 68421905,
      "first_included_block_timestamp": 1767225900,
      "explorer_url": "https://tronscan.org/#/transaction/9f4c1b7e30ad52c8ef6a1d84b0c39f27a5e6d138f4b90c72ae51d63b8407fc25",
      "created_at": 1767225870,
      "updated_at": 1767225930,
      "confirmed_at": 1767225930
    },
    {
      "id": "pcd_5NmXqW7bHt3ZjR9kCvPyAe",
      "payment_channel_id": "pc_2QhKZv6mRt9WdA3nYpLbXf",
      "project_id": "prj_xFukZuAJZR06pLVBh3uwzv",
      "payment_channel_external_id": "customer-42",
      "status": "confirmed",
      "is_final": true,
      "is_test": false,
      "currency": "USDC",
      "network": "ERC20",
      "chain_id": 1,
      "contract_address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
      "gross": "42.5",
      "fee": "0.425",
      "net": "42.075",
      "applied_fee_percent": 1.0,
      "customer_fee_percent": 0,
      "tx_hash": "0x1d7b64e2c05af398b2e714cd9a06f3518cb7e2409df6a1c8305b47ed12f9ca63",
      "transfer_id": "0x1d7b64e2c05af398b2e714cd9a06f3518cb7e2409df6a1c8305b47ed12f9ca63:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48:0x9f2a6c1b4e8d7350ab11c9e5f0d2743b86ce41d9:0",
      "source_address": "0x4b8e1f60d3a97c25be04f7183a5cd9027ef6b14a",
      "destination_address": "0x9f2a6c1b4e8d7350ab11c9e5f0d2743b86ce41d9",
      "block_height": 22984117,
      "first_included_block_timestamp": 1767226020,
      "explorer_url": "https://etherscan.io/tx/0x1d7b64e2c05af398b2e714cd9a06f3518cb7e2409df6a1c8305b47ed12f9ca63",
      "created_at": 1767226020,
      "updated_at": 1767226260,
      "confirmed_at": 1767226260
    }
  ],
  "next_cursor": "CfDJ8JvN…"
}

Akışı doğru sorgulama

  • 01İmleçsiz başlayın. Sayfanın tamamını işleyin.
  • 02next_cursor değerini, sayfa tümüyle işlendikten sonra kalıcı olarak saklayın; öncesinde değil.
  • 03Bir sonraki sorguda geri gönderin. Tekrarlayın.

Bu üç adımın arkasındaki sözleşme:

  • next_cursor asla null olmaz. Boş sayfa dahil her yanıtta bulunur. Konumlar satıcı başına değil, geneldir; bu yüzden hiçbir şeyle eşleşmeyen bir filtrenin bile atladığı konumların ötesine geçmesi gerekir — boşta duran bir entegrasyon da aynı aralığı sonsuza dek yeniden taramaz.
  • null imleçte değil, boş ya da eksik sayfada durun. Fatura listesi next_cursor null olduğunda biter; bu akışın öyle bir sonu yoktur ve bu koşulla yazılan döngü hiç bitmez. limit değerinden az kayıt gelmesi, şu an size kalan bir şey olmadığı anlamına gelir: imleci saklayın, döngüden çıkın ve kendi takviminize göre yeniden sorgulayın.
  • confirmed_from yalnızca ilk sorguyu sınırlar. İkinci sorgudan itibaren nereden devam edeceğinizi saklanan imleç belirler. Aynı değeri imleçle birlikte değiştirmeden göndermeye devam edin: imlecin bağlı olduğu bilgilerden biri de odur, dolayısıyla değeri kaldırmak veya ileri taşımak imleci geçersiz kılar.
  • Sıra monotondur. Bir yatırma bir kez, sabit bir konumda yayımlanır; sonraki bir onay, daha önce okuduğunuz bir onaydan önce görünemez.
  • İlerlemek sizin kararınız. Eski bir imleci yeniden denerseniz aynı yatırmaları tekrar görebilirsiniz. id üzerinden yinelenenleri ayıkladığınız sürece bu güvenlidir — pcd_ kimliği webhook teslimi, akış teslimi ve her tekrar arasında aynı kalır.
  • İmleçlerin süresi 24 saat sonra dolar; bu yüzden işi günde en az bir kez çalışacak şekilde planlayın. İmleç, kaldığınız yerdir; bir hafta rafa kaldırılacak yer imi değil. Daha uzun süre sessiz kalan bir okuyucu 400 pagination_cursor_invalid alır ve confirmed_from ile sınırlanmış biçimde baştan başlar.
  • İmleç ayrıca bağlıdır: kimlik bilginize, onun ortamına, proje kapsamına ve gönderdiğiniz filtrelere. Bir filtreyi değiştirir ya da anahtarın proje erişimini genişletirseniz eski imleç aynı şekilde reddedilir. İlk sayfadan yeniden başlayın: pcd_ üzerinden yinelenenleri ayıkladığınız için tam bir yeniden senkronizasyon zararsızdır.

Akış durduğunda

Tek bir yatırma yanıta dönüştürülemiyorsa akış onu atlamaz ve sayfayı hataya düşürmez. Öncesindeki her şeyi teslim eder, next_cursor değerini o konumda tutar ve hangi yatırmanın neden takıldığını söyler:

{
  "items": [],
  "next_cursor": "CfDJ8JvN…",
  "blocked": {
    "deposit_id": "pcd_4KdQzT9rVn6WsB1mYhFxLg",
    "reason": "booked_auth_missing"
  }
}

blocked, normal hiçbir sayfada bulunmaz. Bulunduğunda:

Neden Anlamı
booked_auth_missing Ödeme onaylandı, ancak muhasebe kaydı henüz yazılmadı.
inconsistent Yatırma, kanalı ve zincir kaydı birbiriyle çelişiyor.
deposit_missing Yayımlanan kayıt artık bir yatırmaya çözülmüyor.
channel_missing Yatırmanın kanalı yüklenemedi.
transfer_missing Yatırmanın kanıtını alacağı bağlı bir zincir kaydı yok.
not_confirmed Yayımlanan bir yatırma onaylanmış durumda değil; bu akışa yalnızca nihai para girer.

Sorgulamayı sürdürün. next_cursor, bilinçli olarak takılan konumun gerisinde kalır; alttaki kayıt onarıldığı anda akış kendiliğinden devam eder ve arada hiçbir şey kaybolmaz. Bunların hepsi bizim tarafımızdaki operasyonel arızadır — sürerse deposit_id ile destekle iletişime geçin.

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ı.
pagination_cursor_invalid 400 İmleç bozuk, süresi dolmuş ya da farklı filtrelere veya farklı bir kapsama bağlı.
field_invalid_format 400 project_id veya payment_channel_id geçerli bir önekli kimlik değil.
field_out_of_range 400 limit, 1–100 aralığının dışında.
query_parameter_unknown 400 Yukarıdaki tabloda bulunmayan bir parametre.

Tam katalog için bkz. Hata Kodları.