Geliştiriciler/Entegrasyon
Ürünler ve siparişler
Bu rehber satın alma sürecinin tamamını adım adım anlatır: bakiyenizi kontrol edin, bir ürün bulun, fiyatını öğrenin, siparişi verin ve kodları alın.
İlgili: Kimlik doğrulama · Genel kurallar · Webhook'lar
#Hesap ve bakiye
#Hesap
GET/api/v1/account, şirket bilgilerinizi ve API erişiminizin açık olup olmadığını gösterir.
{
"merchant_id": "M00000001",
"name": "Acme Shop",
"legal_name": "Acme Shop Ltd",
"tier": "standard",
"billing_email": "[email protected]",
"status": "active",
"kyb_status": "approved",
"api_access_enabled": true,
"default_currency": "USD"
}default_currency, cüzdanınızın para birimidir. Ödediğiniz tüm fiyatlar bu para birimindedir.api_access_enabled, CardV işletmenizi onayladığındatrueolur.
#Bakiye
GET/api/v1/balance, harcayabileceğiniz tutarı gösterir.
{
"currency": "USD",
"balance": "1520.4000",
"reserved_amount": "0.0000",
"available_balance": "1520.4000",
"low_balance_threshold": "200.0000",
"low_balance_notified_at": null,
"is_active": true
}available_balance, şu anda harcayabileceğiniz tutardır:balanceeksireserved_amount.- Tutarı
available_balancedeğerini aşan bir sipariş reddedilir ve hiçbir ücret alınmaz. low_balance_threshold, düşük bakiye e-postasının gönderileceği seviyedir. Bu değeri Portal'dan ayarlarsınız.- Bakiye yüklemek için Portal'ı kullanın.
#Ürünler (SKU'lar)
SKU, satın alabileceğiniz tek bir üründür, örneğin "Steam Wallet 10 USD".
Numarası S000456 gibi görünür. Fiyat sorgusu ve sipariş SKU üzerinden yapılır.
GET/api/v1/skus, satın alabileceğiniz SKU'ları listeler. Örnek:
GET /api/v1/skus?search=steam®ion=US&limit=50&offset=0Filtreler (hepsi isteğe bağlı):
| Filtre | Örnek | Neyle eşleşir |
|---|---|---|
search | steam | SKU numarası, ürün adı veya marka |
brand | Steam | Marka adı (büyük/küçük harf fark etmez) |
region | US | Ülke kodu veya ülke adı |
vertical | gift_card | Ürün grubu |
product_type | pin_code | Teslimat şekli |
Sayfalama: limit (varsayılan 100, en fazla 500) ve offset gönderin.
offset değerini artırarak, count değerine ulaşana kadar sorgulamaya devam edin.
{
"count": 7,
"limit": 1,
"results": [
{
"sku_id": "S000456",
"product_id": "P000123",
"name": "Steam Wallet 10 USD",
"product_name": "Steam Wallet US",
"brand": "Steam",
"region": "US",
"vertical": "gift_card",
"product_type": "pin_code",
"denomination_type": "fixed",
"denomination_value": "10.0000",
"face_currency": "USD",
"merchant_price": "9.2500",
"settlement_currency": "USD",
"availability": "available",
"min_quantity": 1,
"max_quantity": 100,
"required_input_schema": [],
"...": "more fields"
}
],
"filter_options": {"brands": [], "regions": [], "verticals": []}
}GET/api/v1/skus/{sku_id}, aynı alanlarla tek bir SKU döner.
En çok işinize yarayacak alanlar:
| Alan | Anlamı |
|---|---|
sku_id | Fiyat sorgusu ve sipariş için kullandığınız numara. |
merchant_price | Size özel adet fiyatı, settlement_currency para biriminde. |
availability | available veya unavailable. Yalnızca available olan SKU'ları sipariş edin. |
denomination_type | fixed veya range. Bkz. sabit ve aralıklı tutarlar. |
face_currency | Kartın üzerinde yazan para birimi. Cüzdanınızınkinden farklı olabilir. |
min_quantity, max_quantity | Bir sipariş satırında en az ve en fazla kaç adet olabileceği. |
product_type | pin_code (size bir kod verilir) veya direct_charge (hesaba doğrudan yükleme yapılır). |
required_input_schema | Doğrudan yüklemeler için göndermeniz gereken bilgiler. |
brand_logo_url, image_url | CardV'de barındırılan görseller ya da "". |
description, redemption_instructions, terms | Müşterilerinize gösterebileceğiniz metinler. |
İpuçları:
- Yalnızca aktif olan ve hesabınıza açık SKU'ları görürsünüz. Diğer SKU'lar 404 döner.
- SKU listesini 5–15 dakikada bir güncelleyin. Sipariş vermeden hemen önce mutlaka güncel fiyatı sorgulayın.
filter_options, filtrelemede kullanabileceğiniz markaları, bölgeleri ve ürün gruplarını listeler.
#Sabit ve aralıklı tutarlar
SKU'ların çoğunun sabit bir yüz değeri vardır, örneğin 10 USD. Bazı SKU'lar ise aralıklıdır: tutarı müşteriniz seçer, örneğin 5 ile 500 USD arası.
| Tür | Fiyat sorgusunda | Siparişte |
|---|---|---|
fixed | quantity gönderin | amount göndermeyin |
range | quantity ve amount gönderin | amount gönderin |
Aralıklı bir SKU'da amount, min_face_value ile max_face_value arasında olmalıdır.
Tutar face_currency para birimindedir.
#Doğrudan yüklemeler
Bazı ürünler, müşterinizin hesabına (örneğin bir oyun hesabına) doğrudan yükleme yapar. Bunun için CardV'nin hesap bilgilerine ihtiyacı vardır. Gereken bilgiler SKU'da listelenir:
"required_input_schema": [
{"key": "player_id", "label": "Player ID", "required": true},
{"key": "server", "label": "Server", "required": false}
]Değerleri, her birinin key adını kullanarak sipariş satırının inputs alanında gönderin:
"inputs": {"player_id": "123456789", "server": "EU"}"required": falseyazmıyorsa alan zorunludur.- Zorunlu bir değer eksikse sipariş
itemshatasıyla reddedilir. - Bu değerler müşterinizin kişisel verileridir. Onları koruyun (bkz. Güvenlik).
#Fiyat sorgusu
Fiyat sorgusu, belirli bir adet için güncel fiyatı söyler.
GET /api/v1/skus/S000456/quote?quantity=2
GET /api/v1/skus/S000789/quote?quantity=1&amount=25.00{
"sku_id": "S000456",
"settlement_currency": "USD",
"merchant_price": "9.2500",
"quantity": 2,
"total_price": "18.5000",
"min_quantity": 1,
"max_quantity": 100,
"availability": "available"
}- Fiyat sorgusu fiyatı sabitlemez. Fiyatlar her an değişebilir.
- Kendinizi korumak için sipariş verirken
merchant_pricedeğeriniexpected_unit_priceolarak gönderin. Fiyat değiştiyse CardV siparişi reddeder ve hiçbir ücret almaz. - Aralık dışındaki bir adet veya tutar,
quantityya daamounthatasıyla HTTP 400 döner.
#Sipariş verme
POST/api/v1/orders, bir veya daha fazla SKU satın alır ve ödemeyi cüzdanınızdan yapar.
Bu istek imzalı olmalıdır.
{
"external_order_id": "SHOP-20260929-10001",
"items": [
{"sku_id": "S000456", "quantity": 2, "expected_unit_price": "9.2500"},
{"sku_id": "S000789", "amount": "25.00", "expected_unit_price": "23.7500"},
{
"sku_id": "S000900",
"expected_unit_price": "4.9000",
"inputs": {"player_id": "123456789"}
}
]
}| Alan | Zorunlu mu | Anlamı |
|---|---|---|
external_order_id | Evet | Kendi sipariş numaranız, 1–120 karakter. Benzersiz olmalıdır. |
items | Evet | Bir veya daha fazla sipariş satırı. |
items[].sku_id | Evet | Satın alınacak SKU. |
items[].quantity | Hayır | Adet. Varsayılan 1. |
items[].amount | Aralıklı SKU'larda | Satın alınacak yüz değeri. |
items[].expected_unit_price | Önerilir | Sorguda aldığınız merchant_price. Her zaman gönderin. |
items[].inputs | Doğrudan yüklemelerde | Doğrudan yüklemeler için hesap bilgileri. |
CardV siparişi kabul ettiği anda toplam tutarın tamamını cüzdanınızdan düşer. Teslimat ardından arka planda başlar.
Yanıt HTTP 201 olur:
{
"idempotent_replay": false,
"order": {
"order_id": "O-00001234",
"external_order_id": "SHOP-20260929-10001",
"status": "accepted",
"total_amount": "46.2000",
"...": "more fields"
}
}order.order_id değerini saklayın. Bu yanıtta hiçbir zaman kod bulunmaz. Kodları daha sonra alırsınız (Siparişi okuma).
#Reddedilen siparişler
Reddedilen bir sipariş HTTP 400 döner ve hiçbir ücret alınmaz. Nedeni hata anahtarından anlaşılır:
| Anahtar | Neden | Ne yapmalı |
|---|---|---|
items | Fiyat değişmiş, SKU satışta değil, tutar hatalı veya bir bilgi eksik | Fiyatı yeniden sorgulayın, sorunu düzeltip tekrar gönderin |
balance | Cüzdanınızda yeterli para yok | Portal'dan bakiye yükleyin |
risk | Sipariş tutarı veya günlük limitiniz aşıldı | CardV ile iletişime geçin |
external_order_id | Sipariş numaranız başka bir siparişte zaten kullanılmış | Bkz. Güvenli yeniden deneme |
Fiyat değişikliği örneği:
{
"items": "SKU S000456 price changed from 9.2500 to 9.4100 USD; refresh quote and confirm again."
}Tek bir siparişin tutarı, günlük harcama ve günlük sipariş sayısı için limitleri hesap seviyeniz belirler. Günlük limitler 00:00 UTC'de sıfırlanır. Limitlerinizi CardV'ye sorun.
#Güvenli yeniden deneme
Kendi sipariş numaranız (external_order_id), aynı şeyi iki kez satın almanızı önler.
Aynı siparişi aynı sipariş numarasıyla tekrar gönderirseniz CardV sizden tekrar ücret almaz.
Bunun yerine mevcut siparişi döner.
| Gönderdiğiniz | Aldığınız |
|---|---|
| Yeni bir sipariş numarası | HTTP 201. Yeni bir sipariş. Cüzdanınızdan ödeme alınır. |
| Aynı sipariş numarası ve aynı sipariş | HTTP 200 ve "idempotent_replay": true. Mevcut sipariş. Ücret alınmaz. |
| Aynı sipariş numarası ama farklı bir sipariş | external_order_id için HTTP 400. Hiçbir işlem yapılmaz. |
"Aynı sipariş", aynı satırların aynı sırayla ve aynı SKU, adet, tutar ve hesap bilgileriyle gönderilmesi demektir.
expected_unit_price gönderiyorsanız ilk siparişteki fiyatla aynı olmalıdır.
Tekrarlanan sipariş, bakiye ve fiyat kontrollerinden önce tanınır. Bu yüzden fiyat o arada değişmiş olsa bile her zaman ilk sipariş döner.
#Güvenli yeniden deneme akışı
Net bir yanıt alamazsanız aynı siparişi yeniden göndermeniz yeterlidir.
R sipariş numarasıyla POST /orders
├─ 201 veya 200 → order_id'yi saklayın. İşlem tamam.
├─ 400 items / balance / risk → sipariş oluşmadı.
│ Nedeni düzeltip tekrar gönderin. R'yi yeniden kullanabilirsiniz.
├─ 400 external_order_id → R başka bir siparişe ait. Durun ve kontrol edin.
├─ 403 imza hatası → yeniden imzalayıp aynı gövdeyi gönderin.
├─ 429 → Retry-After kadar bekleyin, yeniden imzalayıp aynı gövdeyi gönderin.
└─ zaman aşımı, 5xx veya kopan bağlantı
→ aynı gövdeyi aynı R ile tekrar gönderin.
201 alırsanız ilk istek ulaşmamıştır, 200 alırsanız ulaşmıştır.Kurallar:
- Yanıt kayboldu diye asla yeni sipariş numarası üretmeyin. İlk istek aslında ulaştıysa, yeni numara her şeyi iki kez satın almanıza yol açar.
- Her yeniden gönderimde yeni zaman damgası, nonce ve imza gerekir. Gövde aynı kalır.
#Siparişi okuma
GET/api/v1/orders/{order_id}, siparişi, durumunu ve kodlarını döner.
{
"order_id": "O-00001234",
"external_order_id": "SHOP-20260929-10001",
"status": "succeeded",
"currency": "USD",
"total_amount": "18.5000",
"created_at": "2026-09-29T08:15:30.123456Z",
"updated_at": "2026-09-29T08:15:41.004211Z",
"items": [
{
"sku_id": "S000456",
"product_name": "Steam Wallet US",
"quantity": 2,
"unit_price": "9.2500",
"total_price": "18.5000",
"delivery_count": 2,
"deliveries": [{"...": "see Codes below"}]
}
],
"...": "more fields"
}total_amount, sipariş kabul edildiğinde sizden alınan tutardır.items[].unit_price, bu sipariş için sabitlenen fiyattır.items[].deliveries, kodların tamamını içerir. Bu yanıtı gizli bilgi gibi koruyun.invoice_urlvedelivery_file_url, faturanın ve kodları içeren CSV dosyasının yollarıdır. İkisi de yalnızca Portal'da çalışır. API anahtarıyla çağrıldığında HTTP 403 döner.- Yanıtta ayrıca şunlar da bulunur:
id(eski bir numara, kullanmayın),events(yalnızca görüntüleme amaçlı geçmiş) ve satır bazında teslimat ilerlemesi. Bunları yok sayabilirsiniz. - Bilinmeyen bir sipariş numarası HTTP 404 döner.
#Sipariş durumu ve kodlar
#Durum
accepted ──► processing ──► succeeded
│
├──► partially_succeeded (bazı satırlar teslim edildi, bazıları edilmedi)
│
└──► failed ──► refunded (para cüzdanınıza iade edildi)| Durum | Tamamlandı mı? | Ne yapmalı |
|---|---|---|
accepted | Hayır | Bekleyin. Ödeme cüzdandan alındı, teslimat henüz başlamadı. |
processing | Hayır | Bekleyin. Siparişi tekrar vermeyin. |
succeeded | Evet | Kodları okuyun ve müşterinize iletin. |
partially_succeeded | Evet | Gelenleri teslim edin. Kalan tutar daha sonra iade edilir. |
failed | Henüz değil | refunded durumunu bekleyin. Başarısız olması iade yapıldığı anlamına gelmez. |
refunded | Evet | Para cüzdanınıza geri döndü. |
Webhook kullanmıyorsanız siparişi şu aralıklarla sorgulayın: 5 saniye sonra, ardından 10 sn, 30 sn, 60 sn, sonra 5 dakikada bir. İstek limitini aşmayın. Siparişlerin çoğu birkaç saniyede tamamlanır. Bazıları elle kontrol gerektirir ve saatler sürebilir.
#Kodlar
Teslim edilen her adet, items[].deliveries içinde bir nesnedir:
{
"status": "stored",
"delivery_type": "card_pin",
"display_fields": [
{"key": "card_number", "label": "Card number", "value": "X1234", "kind": "secret"},
{"key": "pin_code", "label": "PIN", "value": "9876", "kind": "secret"}
],
"redeem_url": "",
"expiry_date": "2027-09-29",
"instructions": "Redeem at ...",
"is_masked": false
}- Müşterinize
display_fieldsalanını gösterin: her birinde birlabelve birvaluevardır.redeem_url,expiry_dateveinstructionsboş değilse onları da gösterin. kind, kodlar ve PIN'ler içinsecret, seri numarası gibi bilgiler içinreferenceolur.delivery_typene aldığınızı söyler:code,card_pin,link,code_linkveyaqr. Yeni türler eklenebilir. Bu yüzden gösterimi her zamandisplay_fieldsüzerinden kurun.linkteslimatlarında kodun kendisiredeem_urladresidir. Gizli tutun.statusdeğerivoidedolan bir adedi müşterinize asla vermeyin.- Doğrudan yükleme ürünlerinde genellikle teslimat nesnesi olmaz.
succeeded, hesaba yüklemenin yapıldığı anlamına gelir. card_numbervepin_codegibi kopyalar ayrı alanlar olarak da gelir. Bunlar boş olabilir.- Webhook'lar hiçbir zaman kod içermez. Webhook geldikten sonra siparişi okuyun.
Entegrasyonla ilgili sorunuz mu var? Merchant ID’nizi ve sipariş ya da istek kimliğini ekleyerek [email protected] adresine yazın.