# Kargoya vermek

> **Ne yaparsınız:** Siparişin kargo fiyatını sorar, BasitKargo ile gönderi açar, etiketi indirir, takibi izler ve gerekirse gönderiyi iptal edersiniz.
> **Hangi uçlar:** [Kargo fiyatı sor](https://developer.siparis.app/uc/kargo-fiyati-sor), [Gönderi oluştur](https://developer.siparis.app/uc/gonderi-olustur), [Gönderiyi getir](https://developer.siparis.app/uc/gonderiyi-getir), [Kargo etiketini indir](https://developer.siparis.app/uc/kargo-etiketini-indir), [Siparişin gönderilerini listele](https://developer.siparis.app/uc/siparisin-gonderilerini-listele), [Gönderiyi iptal et](https://developer.siparis.app/uc/gonderiyi-iptal-et)
> **Gereken izin:** Fiyat, açma ve iptal için `shipments:write`; okuma için `shipments:read`, etiket için ayrıca `personal_data:read`.

API kökü `https://api.siparis.app/v1`. Fiyat sor → gönderi aç → etiketi indir → takip ve olayları izle → gerekiyorsa iptal et. İşletmenin BasitKargo hesabı bağlı, firma açık ve sipariş onaylanmış veya hazırlanıyor olmalıdır. Paneldeki **Kargoya ver** ile aynı bakiye, adres, koli ve kapıda ödeme kuralları uygulanır.

## 1. Bağlantıyı hazırlayın

**İşletme ayarları > Geliştirici > Depo / kargo yazılımı** şablonunu seçin. Sipariş altındaki liste ayrıca `orders:read`, olaylar `events:read`, maliyet alanları `costs:read` kapsamını (erişim iznini) ister. Marka sınırlı bağlantı yalnız o markanın siparişlerini görür; başka markanın kimliği 404 döner. İşletme bağlantısı bütün izinli markalarda çalışır.

Aşağıdaki değişkenlere kendi anahtarınızı ve [sipariş listesinden](https://developer.siparis.app/siparisleri-listelemek) aldığınız dış kimliği yazın. Anahtarı sohbete veya kaynak koduna koymayın.

```bash
export SIPARIS_API_URL="https://api.siparis.app/v1"
export SIPARIS_API_KEY="KENDI_API_ANAHTARINIZ"
export SIPARIS_ORDER_ID="ord_1234567890abcdef1234567890abcdef"
```

## 2. Fiyat sorun

Bu **yan etkisiz POST** isteği `Idempotency-Key` (tekrar anahtarı) istemez: bakiye düşmez, sipariş ve koli kaydı değişmez. Tutarlar TRY cinsinden ondalık metindir. İşletme başına **60 saniyede 20 fiyat sorgusu** sınırı vardır ve bütün bağlantılar aynı sayacı paylaşır; farklı koli ölçüsü veya yeni anahtar bu sınırı yenilemez. Aşımda `429 quote_rate_limited` gelir; gönderi açma bu sayaçtan etkilenmez.

```bash
curl --fail-with-body -sS -X POST \
  "$SIPARIS_API_URL/orders/$SIPARIS_ORDER_ID/shipments/quote" \
  -H "Authorization: Bearer $SIPARIS_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{}'
```

Örnek HTTP 200 yanıtı (uydurma veri):

```json
{
  "boxes": [
    {
      "depth": 20,
      "height": 20,
      "weight": 1,
      "width": 20
    }
  ],
  "carriers": [
    {
      "available": true,
      "cod_fee": "29.90",
      "code": "YURTICI",
      "detail": null,
      "fee": "124.80",
      "name": "Yurtiçi Kargo",
      "note": null,
      "problem_code": null
    }
  ],
  "cod_amount": "120.00",
  "cod_type": "cash",
  "default_carrier": "YURTICI",
  "order": "ord_1234567890abcdef1234567890abcdef",
  "package_version": "0123456789abcdef",
  "package_warning": null,
  "payment_warning": null
}
```



`carriers` açık firmaları verir; `code` gönderi açarken kullanılır, `fee` tahmini toplam ücrettir. `available=false` ise `problem_code` ve `detail` engeli açıklar. `note` varsa tahsilat bedeli henüz kesinleşmemiştir; maliyet sonradan değişebilir. Fiyat sorgusu bakiye ayırmaz, açılışta yeniden kontrol edilir. Yanıt alanlarının tamamı [Kargo fiyatı sor](https://developer.siparis.app/uc/kargo-fiyati-sor) sayfasındadır.

Ürün ölçüleri eksikse `package_warning` değerini kullanıcıya gösterin. Gerçek ölçüleri kullanmak için sorguya ve açılışa aynı `package` nesnesini gönderin (ölçüler cm, ağırlık koli başına kg):

```json
{"package":{"boxes":[{"count":1,"width":20,"depth":30,"height":15,"weight":2}],"version":"FIYAT_YANITINDAKI_PACKAGE_VERSION"}}
```

`version` isteğe bağlıdır; verilirse arada değişen koli bilgisiyle açılış reddedilir. Sorguda verilen ölçüler kalıcı değildir; açılışta panelin koli düzeltme yolu kullanılır.

## 3. Gönderiyi açın

Fiyat yanıtından uygun firmanın kodunu seçin. Her yeni işte benzersiz tekrar anahtarı (aynı isteği güvenle yeniden göndermek için ürettiğiniz metin) üretin; ağ tekrarında bu değişkeni değiştirmeyin. Aşağıdaki komutlar `python3` kullanır.

İlk örnek için zorunlu alanlar (POST /v1/orders/{id}/shipments):

| Alan | Tür | Açıklama | Örnek |
| --- | --- | --- | --- |
| `carrier` | metin (en çok 40 karakter) | Fiyat yanıtındaki açık kargo firmasının code değeri; standart gönderi hizmeti. | `"YURTICI"` |

Bütün alanlar: [Gönderi oluştur](https://developer.siparis.app/uc/gonderi-olustur).

```bash
export SIPARIS_SHIPMENT_KEY="$(python3 -c 'import uuid; print(uuid.uuid4())')"
export SIPARIS_CARRIER="YURTICI"
curl --fail-with-body -sS -D gonderi-basliklari.txt -o gonderi.json \
  -X POST "$SIPARIS_API_URL/orders/$SIPARIS_ORDER_ID/shipments" \
  -H "Authorization: Bearer $SIPARIS_API_KEY" \
  -H "Idempotency-Key: $SIPARIS_SHIPMENT_KEY" \
  -H 'Content-Type: application/json' \
  -d "{\"carrier\":\"$SIPARIS_CARRIER\"}"
export SIPARIS_SHIPMENT_ID="$(python3 -c 'import json; print(json.load(open("gonderi.json"))["id"])')"
```

Örnek HTTP 202 yanıtı (uydurma veri):

```json
{
  "carrier": "YURTICI",
  "cod_amount": "120.00",
  "collected_amount": null,
  "combined": false,
  "created_at": "2026-10-16T09:00:00Z",
  "currency": "TRY",
  "delivered_at": null,
  "id": "shp_1234567890abcdef1234567890abcdef",
  "shipping_fee": "0.00",
  "state": "ready",
  "status": "pending",
  "updated_at": "2026-10-16T09:00:00Z"
}
```



`202` işin kaydedildiğini belirtir; `status=pending` henüz barkod oluşmadığı anlamındadır. `Location` gönderiyi izleme yoludur. İsteğe bağlı `If-Match` başlığında siparişin son `ETag` değerini (sürüm etiketi) gönderebilirsiniz; sipariş bu arada değiştiyse gönderi açılmaz.

Bağlantı kesilirse **aynı anahtar ve aynı gövdeyle** gönderi açma komutunu tekrar edin. `Idempotent-Replayed: true` gelirse iş yeniden çalışmamıştır; aynı gönderinin güncel hali gelir. İlk yanıt 202 ise tekrarda da 202 korunur; bu yüzden gövdedeki durumu okuyun. Belirsiz dış servis sonucunda aynı gönderi bekler; ikinci gönderi açılmaz. `failed` kesin başarısızlıkta `error_code` nedenini verir. Nedeni düzelttikten sonra yeni iş için yeni anahtar kullanın.

Birleştirmek için açılışa ve fiyat sorgusuna `merge_orders` içinde diğer siparişlerin `ord_` kimliklerini ekleyin. Otomatik birleştirme yapılmaz. Aynı marka, alıcı, adres ve depo gerekir; kapıda nakit ile kapıda kart birlikte gönderilmez. Gönderici adresi siparişin deposudur; bu uçta başka gönderici adresi seçilmez. Ortak gönderide elle `package` verilemez; önce siparişlerin kolilerini panelde düzeltin.

Birleşik grubun gönderisi zaten açılmışsa yeni bir açılış isteği `409 shipment_not_allowed` döner; güncel gönderiyi siparişin gönderi listesinden okuyun. API’deki ilk açılışın aynı tekrar anahtarıyla yinelenmesi ise aynı gönderiyi döndürmeye devam eder.

## 4. Hazır olmasını bekleyin ve etiketi indirin

```bash
curl --fail-with-body -sS \
  "$SIPARIS_API_URL/shipments/$SIPARIS_SHIPMENT_ID" \
  -H "Authorization: Bearer $SIPARIS_API_KEY"
```

Örnek HTTP 200 yanıtı (uydurma veri):

```json
{
  "carrier": "YURTICI",
  "cod_amount": "120.00",
  "collected_amount": null,
  "combined": true,
  "created_at": "2026-10-16T09:00:00Z",
  "currency": "TRY",
  "delivered_at": null,
  "id": "shp_1234567890abcdef1234567890abcdef",
  "shipping_fee": "0.00",
  "state": "ready",
  "status": "created",
  "updated_at": "2026-10-16T09:00:00Z"
}
```



`pending` ise birkaç saniye sonra yeniden okuyun. `failed` ise hatayı giderin; `created` olduğunda etiketi indirin. Etiket `image/svg+xml` döner; panelde gösterilen sağlayıcı SVG’si korunur. `personal_data:read` izni olmayan veya iptal edilmiş anahtar indiremez; etiketi ortak önbelleğe koymayın.

```bash
curl --fail-with-body -sS \
  "$SIPARIS_API_URL/shipments/$SIPARIS_SHIPMENT_ID/label" \
  -H "Authorization: Bearer $SIPARIS_API_KEY" \
  -D etiket-basliklari.txt \
  -o kargo-etiketi.svg
```

Her koli ayrı SVG etiketidir; varsayılan `page=1` ilk koliyi indirir. `etiket-basliklari.txt` içindeki `X-Label-Pages` toplam etiket sayısını verir; birden çok koli varsa kalan sayfaları da indirin. Örneğin ikinci koli için:

```bash
curl --fail-with-body -sS \
  "$SIPARIS_API_URL/shipments/$SIPARIS_SHIPMENT_ID/label?page=2" \
  -H "Authorization: Bearer $SIPARIS_API_KEY" \
  -o kargo-etiketi-2.svg
```

Olmayan bir sayfa `404 not_found` döner. Güvenlik başlıkları ve dosya adı [Kargo etiketini indir](https://developer.siparis.app/uc/kargo-etiketini-indir) sayfasındadır.

SVG dosyasını tarayıcıda açıp yazdırabilirsiniz. PDF gerekiyorsa kendi tarafınızda dönüştürün; örneğin bilgisayarınızda librsvg’nin `rsvg-convert` aracı kuruluysa:

```bash
rsvg-convert --format=pdf --output=kargo-etiketi.pdf kargo-etiketi.svg
```

## 5. Takip ve olaylar

Gönderi okuması barkod, takip numarası ve durumu verir; siparişin bütün gönderileri [Siparişin gönderilerini listele](https://developer.siparis.app/uc/siparisin-gonderilerini-listele) ucundadır. Firma takip numarası hazır değilse barkodu takip numarası olarak göstermeyin. Entegrasyonunuzu kargo firmasının kodunu taşıyan `status` yerine firmadan bağımsız `state` (ör. `ready`, `in_transit`, `delivered`) ve kapıda ödemede `cod_state` alanına bağlayın; değerler [Kodlar ve durumlar](https://developer.siparis.app/referans#gonderi-ortak-durumlari) sayfasındadır.

```bash
curl --fail-with-body -sS --get "$SIPARIS_API_URL/events" \
  -H "Authorization: Bearer $SIPARIS_API_KEY" \
  --data-urlencode 'types=shipment.created,shipment.status_changed' \
  --data-urlencode 'limit=50'
```

`shipment.created` fiziksel gönderi oluşunca, `shipment.status_changed` açılış beklerken, başarısızlıkta ve sonraki durum değişikliklerinde gelir. Olayın `changes` alanında firmanın kodunun (`status`, `cod_status`) yanında firmadan bağımsız `state` ve `cod_state` de gelir. Olaydaki kaynak kimliğiyle güncel gönderiyi okuyun. Yanıttaki `next_cursor` değerini (sonraki okumanın yer imi) saklayın; devamı için [olaylar](https://developer.siparis.app/olaylar), bildirim için [webhook](https://developer.siparis.app/webhook) rehberini kullanın. Gönderi durumlarının anlamı [Kodlar ve durumlar](https://developer.siparis.app/referans#gonderi-durumlari) sayfasındadır.

## 6. Gerekirse iptal edin

Panelde iptal edilebilen, henüz kurye tarafından alınmamış gönderiler aynı kuralla iptal edilir. Açılışı bekleyen gönderide önce sonucu izleyin. Ortak gönderinin iptali bütün üye siparişlerin kargosunu iptal eder; siparişlerin kendisi iptal edilmez.

```bash
export SIPARIS_CANCEL_KEY="$(python3 -c 'import uuid; print(uuid.uuid4())')"
curl --fail-with-body -sS -X POST \
  "$SIPARIS_API_URL/shipments/$SIPARIS_SHIPMENT_ID/cancel" \
  -H "Authorization: Bearer $SIPARIS_API_KEY" \
  -H "Idempotency-Key: $SIPARIS_CANCEL_KEY" \
  -H 'Content-Type: application/json' \
  -d '{}'
```

Örnek HTTP 202 yanıtı (uydurma veri):

```json
{
  "cancellation_status": "pending",
  "carrier": "YURTICI",
  "cod_amount": "120.00",
  "collected_amount": null,
  "combined": true,
  "created_at": "2026-10-16T09:00:00Z",
  "currency": "TRY",
  "delivered_at": null,
  "id": "shp_1234567890abcdef1234567890abcdef",
  "shipping_fee": "0.00",
  "state": "ready",
  "status": "created",
  "updated_at": "2026-10-16T09:00:00Z"
}
```



202 yanıtında `cancellation_status` ile iptal işini izleyin; `pending` veya `unknown` tamamlandı demek değildir. Sağlayıcı doğrulayınca `status=cancelled` olur. BasitKargo’nun paneldeki bakiye iadesi uygulanır; bu yanıt müşteriye para iadesi yapmaz. Zaten iptal edilmiş gönderiye yeni anahtarla iptal 200 döner, ikinci ücret/iade işlemi yapılmaz.

## Bakiye ve kapıda ödeme

Bakiye BasitKargo panelinden yüklenir. Bakiye okunamazsa paneldeki gibi son denetim gönderi açılırken sağlayıcıda yapılır. Kapıda tahsil edilecek tutar siparişin ödeme yöntemi ve kalan borcundan hesaplanır; kapora düşülür, peşin ödenen tutar tekrar tahsil edilmez. Bu uçta tahsilat tutarı veya ödeme yöntemi değiştirilmez. Tahsilat bedelinin KDV durumu sağlayıcının bu fiyat yanıtında belirtilmemiştir; ayrıca KDV eklenmez. Kapıda ödeme ayarı ve firma desteği panelle aynıdır.

## Sık hatalar

| Yanıt | Ne yapmalısınız? |
| --- | --- |
| `400 shipping_balance_insufficient` | BasitKargo bakiyesini yükleyin; yeni anahtarla açın. |
| `400 shipping_address_invalid` | Siparişteki telefon, il, ilçe, mahalle ve açık adresi düzeltin. |
| `400 shipping_carrier_disabled` | Fiyat yanıtındaki açık firmayı seçin. |
| `400 shipping_cod_unavailable` | Hesabın kapıda ödeme ayarını ve firmanın ödeme türü desteğini kontrol edin. |
| `409 shipping_not_connected` | İşletme ayarları > Kargo’dan BasitKargo hesabını bağlayın. |
| `409 shipment_not_allowed` | Güncel siparişi/gönderiyi okuyun; bekleyen işlemin sonucunu izleyin. |
| `409 shipment_label_not_ready` | Açılış tamamlanmamıştır veya gönderi iptaldir. |
| `429 quote_rate_limited` | İşletmenin fiyat sorgulama sınırı dolmuştur; Retry-After saniye bekleyin. Gönderi açma bu sayaçtan etkilenmez. |
| `429 shipping_rate_limited` / `503 shipping_unavailable` | Retry-After saniye bekleyin; ağ tekrarında aynı anahtarı koruyun. |
| `502 shipping_provider_error` | Aynı gönderinin etiketini daha sonra yeniden indirin. |

İlk 4xx iş hatası makbuza yazılır; düzeltilmiş yeni denemede yeni anahtar gerekir. Genel API hız sınırında `429 rate_limit_exceeded` gelir; fiyat ve etiket istekleri 10’ar puandır.
