E-ticaret & Stok Yönetimi

Kargo Entegrasyonu: Yurtiçi, Aras, MNG ve Sürat API

Fatih Algül
26.03.2026 259 görüntülenme

Kargo Entegrasyonu Nedir ve Neden Önemlidir?

E-ticaret dünyasında sipariş yönetiminin en kritik halkalarından biri kargo entegrasyonudur. Müşteri siparişi verdikten sonra, kargo sürecinin otomatik olarak başlatılması, takip numarasının oluşturulması ve durum güncellemelerinin anlık olarak alınması hem operasyonel verimliliği artırır hem de müşteri memnuniyetini doğrudan etkiler. Türkiye'deki dört büyük kargo firması — Yurtiçi Kargo, Aras Kargo, MNG Kargo ve Sürat Kargo — geliştiricilere RESTful API'ler sunarak bu süreci programatik olarak yönetmeye olanak tanır.

Bu yazıda her bir kargo firmasının API yapısını, kimlik doğrulama yöntemlerini, gönderi oluşturma ve sorgulama adımlarını detaylı şekilde inceleyeceğiz.

Genel Mimari Yaklaşım

Kargo entegrasyonlarını tek bir yapı altında toplamak için Adapter (veya Strategy) tasarım deseni kullanmanız önerilir. Bu sayede her kargo firması için ayrı bir sınıf yazarken, ortak bir arayüz üzerinden çalışabilirsiniz:

from abc import ABC, abstractmethod

class CargoProvider(ABC):
    @abstractmethod
    def create_shipment(self, order: dict) -> dict:
        """Gönderi oluşturur, takip numarası döner."""
        pass

    @abstractmethod
    def get_tracking(self, tracking_number: str) -> dict:
        """Gönderi durumunu sorgular."""
        pass

    @abstractmethod
    def cancel_shipment(self, tracking_number: str) -> bool:
        """Gönderiyi iptal eder."""
        pass

Bu soyut sınıfı her kargo firması için implemente ettiğinizde, iş mantığınız kargo firmasından bağımsız hale gelir. Yeni bir firma eklemek istediğinizde sadece yeni bir adapter yazmanız yeterlidir.

Yurtiçi Kargo API Entegrasyonu

Yurtiçi Kargo, Türkiye'nin en yaygın kargo ağlarından birine sahiptir ve SOAP tabanlı bir web servisi sunar. Ancak güncel sürümlerinde REST desteği de mevcuttur. Entegrasyon için size bir kullanıcı adı, şifre ve müşteri kodu (firma kodu) verilir.

Kimlik Doğrulama

Yurtiçi Kargo API'sine her istekte kullanıcı bilgileri gönderilir. OAuth veya token tabanlı bir yapı yerine, istek gövdesinde kimlik bilgileri taşınır:

import requests

YURTICI_BASE_URL = "https://webservices.yurticikargo.com/api"

auth_payload = {
    "userName": "FIRMA_KULLANICI_ADI",
    "password": "FIRMA_SIFRE",
    "custCode": "MUSTERI_KODU"
}

Gönderi Oluşturma

def create_yurtici_shipment(order):
    payload = {
        **auth_payload,
        "shipments": [{
            "receiverName": order["customer_name"],
            "receiverPhone": order["phone"],
            "receiverAddress": order["address"],
            "cityCode": order["city_code"],
            "townCode": order["district_code"],
            "desi": order["desi"],
            "cargoCount": order["package_count"],
            "productType": "D",  # Dosya/Paket
            "description": f"Siparis #{order['order_id']}"
        }]
    }

    response = requests.post(
        f"{YURTICI_BASE_URL}/shipment/create",
        json=payload
    )
    result = response.json()

    if result.get("status") == "OK":
        return {
            "tracking_number": result["data"]["trackingNumber"],
            "barcode_url": result["data"]["barcodeUrl"]
        }
    raise Exception(f"Yurtici hata: {result.get('message')}")

Önemli: Yurtiçi Kargo'da şehir ve ilçe kodları numerik değerlerdir. Bu kodları /address/cities ve /address/towns endpoint'lerinden çekerek kendi veritabanınızda cache'lemeniz önerilir.

Aras Kargo API Entegrasyonu

Aras Kargo, RESTful yapıda modern bir API sunar. Entegrasyon için API Key ve müşteri kodu kullanılır. Aras'ın API'si genellikle daha temiz bir JSON yapısına sahiptir.

Kimlik Doğrulama ve Gönderi Oluşturma

ARAS_BASE_URL = "https://customerservices.araskargo.com.tr/api"
ARAS_HEADERS = {
    "Content-Type": "application/json",
    "ApiKey": "ARAS_API_KEY"
}

def create_aras_shipment(order):
    payload = {
        "CustomerCode": "MUSTERI_KODU",
        "InvoiceNumber": order["order_id"],
        "ReceiverName": order["customer_name"],
        "ReceiverPhone": order["phone"],
        "ReceiverCity": order["city"],
        "ReceiverDistrict": order["district"],
        "ReceiverAddress": order["address"],
        "PieceCount": order["package_count"],
        "Weight": order["weight"],
        "VolumetricWeight": order["desi"],
        "PaymentType": 1,  # 1: Gönderici Ödemeli
        "IsCOD": False
    }

    response = requests.post(
        f"{ARAS_BASE_URL}/shipment",
        json=payload,
        headers=ARAS_HEADERS
    )
    result = response.json()
    return {
        "tracking_number": result["TrackingNumber"],
        "cargo_key": result["CargoKey"]
    }

Kargo Takibi

def track_aras_shipment(tracking_number):
    response = requests.get(
        f"{ARAS_BASE_URL}/tracking/{tracking_number}",
        headers=ARAS_HEADERS
    )
    data = response.json()
    return {
        "status": data["StatusDescription"],
        "last_update": data["LastTransactionDate"],
        "movements": [
            {
                "date": m["Date"],
                "location": m["UnitName"],
                "description": m["Description"]
            }
            for m in data.get("Movements", [])
        ]
    }

MNG Kargo API Entegrasyonu

MNG Kargo, token bazlı kimlik doğrulama kullanan bir REST API sunar. Önce bir token alırsınız, ardından bu token ile işlemlerinizi gerçekleştirirsiniz.

Token Alma

MNG_BASE_URL = "https://api.mngkargo.com.tr/api/v2"

def get_mng_token():
    response = requests.post(
        f"{MNG_BASE_URL}/auth/token",
        json={
            "customerNumber": "MNG_MUSTERI_NO",
            "password": "MNG_SIFRE",
            "identityType": 1
        }
    )
    data = response.json()
    return data["jwt"]

# Token'ı önbelleğe alın, her istekte yeniden almayın
mng_token = get_mng_token()
mng_headers = {
    "Authorization": f"Bearer {mng_token}",
    "Content-Type": "application/json"
}

Gönderi Oluşturma

def create_mng_shipment(order):
    payload = {
        "referenceId": str(order["order_id"]),
        "receiver": {
            "fullName": order["customer_name"],
            "phone": order["phone"],
            "cityCode": order["city_code"],
            "districtName": order["district"],
            "address": order["address"]
        },
        "pieces": [{
            "weight": order["weight"],
            "desi": order["desi"],
            "content": order.get("description", "E-ticaret gonderisi")
        }],
        "paymentType": "SENDER",
        "shipmentServiceType": "STANDART"
    }

    response = requests.post(
        f"{MNG_BASE_URL}/shipment",
        json=payload,
        headers=mng_headers
    )
    result = response.json()
    return {
        "tracking_number": result["trackingNumber"],
        "barcode_zpl": result.get("barcodeZpl")
    }

Dikkat: MNG Kargo token'larının belirli bir süresi (genellikle 24 saat) vardır. Token'ın süresini takip ederek otomatik yenileme mekanizması kurmanız önerilir. Bunu basit bir dekoratör ile çözebilirsiniz:

import time

class MNGTokenManager:
    def __init__(self):
        self.token = None
        self.expires_at = 0

    def get_headers(self):
        if time.time() >= self.expires_at:
            self.token = get_mng_token()
            self.expires_at = time.time() + 82800  # 23 saat
        return {
            "Authorization": f"Bearer {self.token}",
            "Content-Type": "application/json"
        }

Sürat Kargo API Entegrasyonu

Sürat Kargo, SOAP ve REST olmak üzere iki farklı API seçeneği sunar. Yeni projelerde REST API tercih edilmelidir. Kimlik doğrulaması için kullanıcı adı ve şifre çifti ile Basic Auth veya token tabanlı erişim sağlanır.

Gönderi Oluşturma

SURAT_BASE_URL = "https://api.suratkargo.com.tr/api"
SURAT_AUTH = ("KULLANICI_ADI", "SIFRE")

def create_surat_shipment(order):
    payload = {
        "customerReferenceCode": str(order["order_id"]),
        "receiverName": order["customer_name"],
        "receiverPhoneNumber": order["phone"],
        "receiverProvince": order["city"],
        "receiverCounty": order["district"],
        "receiverAddress": order["address"],
        "packageCount": order["package_count"],
        "weight": order["weight"],
        "desi": order["desi"],
        "paymentType": "G",  # G: Gönderici Ödemeli
        "collectionType": "N"  # N: Normal, K: Kapıda Ödeme
    }

    response = requests.post(
        f"{SURAT_BASE_URL}/shipment/create",
        json=payload,
        auth=SURAT_AUTH
    )
    result = response.json()
    return {
        "tracking_number": result["trackingNumber"],
        "label_pdf": result.get("labelUrl")
    }

Webhook ve Durum Güncellemeleri

Kargo firmalarının çoğu, gönderi durumu değiştiğinde sizin belirlediğiniz bir URL'e bildirim gönderebilir. Bu webhook mekanizması, sürekli polling yapmak yerine olay tabanlı mimari kurmanıza olanak tanır:

from flask import Flask, request

app = Flask(__name__)

@app.route("/webhooks/cargo", methods=["POST"])
def cargo_webhook():
    data = request.json
    provider = data.get("provider")
    tracking = data.get("trackingNumber")
    status = data.get("status")

    # Sipariş durumunu güncelle
    update_order_status(tracking, status)

    # Müşteriye bildirim gönder
    if status in ("DELIVERED", "TESLIM_EDILDI"):
        send_customer_notification(tracking, "Kargonuz teslim edildi!")
    elif status in ("IN_TRANSIT", "TRANSFER"):
        send_customer_notification(tracking, "Kargonuz yolda!")

    return {"status": "ok"}, 200

Webhook desteği olmayan firmalarda, bir cron job veya Celery task ile belirli aralıklarla (örneğin her 30 dakikada bir) teslim edilmemiş gönderilerin durumunu sorgulayabilirsiniz.

Hata Yönetimi ve En İyi Pratikler

  • Retry mekanizması kurun: Kargo API'leri zaman zaman geçici hatalar verebilir. Exponential backoff ile 3 denemeye kadar tekrar edin. tenacity veya requests.adapters.HTTPAdapter bu iş için idealdir.
  • Timeout belirleyin: Her API çağrısında mutlaka timeout=(5, 30) parametresi kullanın. İlk değer bağlantı, ikinci değer okuma zaman aşımıdır.
  • Loglama yapın: Her istek ve yanıtı loglayın. Kargo firmasıyla yaşanan anlaşmazlıklarda bu loglar kritik öneme sahiptir.
  • Idempotency sağlayın: Aynı sipariş için birden fazla gönderi oluşturulmasını engellemek adına, sipariş ID'sini referans kodu olarak gönderin ve mükerrer kontrol mekanizması kurun.
  • Sandbox ortamlarını kullanın: Dört firmanın da test ortamları mevcuttur. Canlıya geçmeden önce tüm akışları sandbox üzerinde doğrulayın.
  • Rate limiting'e dikkat edin: Özellikle toplu gönderi oluşturma ve sorgulama işlemlerinde API limitlerini aşmamaya özen gösterin. Toplu işlemleri batch endpoint'leri üzerinden yapın.

Birleşik Kargo Servisi Örneği

Tüm kargo firmalarını tek bir servis altında toplamak için adapter desenini kullanarak şu şekilde bir yapı kurabilirsiniz:

class CargoService:
    _providers = {
        "yurtici": YurticiProvider,
        "aras": ArasProvider,
        "mng": MNGProvider,
        "surat": SuratProvider,
    }

    def __init__(self, provider_name: str):
        provider_class = self._providers.get(provider_name)
        if not provider_class:
            raise ValueError(f"Desteklenmeyen kargo: {provider_name}")
        self.provider = provider_class()

    def ship(self, order: dict) -> dict:
        result = self.provider.create_shipment(order)
        save_tracking_to_db(order["order_id"], result["tracking_number"])
        return result

    def track(self, tracking_number: str) -> dict:
        return self.provider.get_tracking(tracking_number)

# Kullanım
service = CargoService("aras")
result = service.ship(order_data)
print(f"Takip No: {result['tracking_number']}")

Sonuç

Yurtiçi, Aras, MNG ve Sürat Kargo API entegrasyonları farklı kimlik doğrulama yöntemleri ve veri yapıları kullansa da, ortak bir soyutlama katmanı ile yönetilebilir hale gelir. Adapter deseni sayesinde yeni kargo firmaları eklemek veya mevcut firmaları değiştirmek iş mantığınızı etkilemez. Hata yönetimi, loglama ve idempotency gibi konulara özen göstererek güvenilir ve sürdürülebilir bir kargo altyapısı kurabilirsiniz. Sandbox ortamlarında kapsamlı testler yaptıktan sonra canlıya geçmeniz, olası sorunları en aza indirecektir.

Yazar Hakkında
Fatih Algül
TechSoft Solutions
Proje mi var?

Yazılım, IoT veya otomasyon konularında destek almak ister misiniz?

İletişime Geç