Ürün Oluşturma

Mağazaya yeni ürün ekler. Ürün taslak olarak oluşur, satışa çıkması Milagron onay sürecinden sonra gerçekleşir.

Gerekli yetki: product:write

Endpoint

POST /integration/product/sellers/{sellerId}/products

Production
https://api.milagron.com/integration/product/sellers/{sellerId}/products
Stage
Yakında
ID tabanlı referanslar: Marka, kategori ve özellik (attribute) alanlarının tamamı isim değil ID ile gönderilir. Geçerli ID'leri Katalog & ID Keşfi uçlarından alın.
Tek kategori ID'si. Ürün, kategori ağacının yaprak seviyesine açılır ve istekte yalnızca categoryId gönderilir; alt ve ana kategori sunucu tarafında türetilir. Ağacın tamamı tek çağrıda gelir: GET .../categories.
Özellikler kategoriye bağlıdır. Bir üründe kullanılabilecek özellikler, seçilen categoryId için tanımlanmış eşlemeyle sınırlıdır. İstek gövdesini kurgulamadan önce Kategori Özellikleri (GET .../categories/{categoryId}/attributes) ucunu çağırın.

İstek Gövdesi

Üst Düzey Alanlar

AlanTipZorunluAçıklama
titlestringEvetÜrün başlığı (en fazla 255 karakter).
descriptionstringEvetÜrün açıklaması (HTML desteklenir).
brandIdintegerEvetMarka ID'si. GET .../brands ile alınır; satıcıya tanımlı olmalıdır.
categoryIdintegerEvetTek kategori alanı. Kategori ağacının yaprak seviyesi ("leaf": true). Alt ve ana kategori sunucu tarafında ağaçtan türetilir. Ürünün özellikleri ve KDV oranları buna bağlıdır. Eski ad productTypeId hâlâ kabul edilir.
taxRateintegerEvetKDV oranı. Yaprak kategorinin taxRates listesindeki değerlerden biri olmalıdır.
deliveryOptionsobjectEvetminDeliveryDays ve maxDeliveryDays (gün, 0 ≤ min ≤ max ≤ 365).
imagesarrayEvetGörsel URL listesi (en az 1, en fazla 50). "https://..." veya { "url": "https://..." } biçiminde.
variantsarrayEvetVaryant listesi (en az 1, en fazla 100). Ürünün özellikleri bu listeden türetilir; aşağıya bakın.
sizeChartobjectHayırBeden tablosu (ör. { "type": "html", "content": "<table>..." }).

Varyant Alanları

AlanTipZorunluAçıklama
barcodestringEvetBarkod (en fazla 100 karakter). Sistem genelinde benzersiz olmalıdır.
stockCodestringEvetSKU (en fazla 100 karakter). Sistem genelinde benzersiz olmalıdır.
stockintegerEvetStok adedi (≥ 0).
price.salePricenumberEvetSatış fiyatı (> 0).
price.listPricenumberHayırListe (indirim öncesi) fiyatı. 0, boş veya satış fiyatına eşitse indirimsiz kabul edilir.
attributesarrayKoşulluVaryantın özellik değerleri: { "attributeId": x, "attributeValueId": y }. Ürünün kullandığı özellikler bu alandan türetilir; tüm varyantlar aynı özellik kümesini bildirmelidir. Tek varyantlı üründe boş bırakılır veya hiç gönderilmez.
Ürün seviyesinde ayrı bir attributes listesi gönderilmez. Ürünün hangi özellikleri kullandığı varyantlardan çıkarılır. Seçenek sırası (varyant adı "Siyah / S" ve vitrindeki seçenek sırası) kategori özellik sırasından gelir; istekteki JSON sırası sonucu etkilemez.

Örnek İstek

{
  "title": "Pamuklu Basic Tişört",
  "description": "<p>%100 pamuk, rahat kesim.</p>",
  "brandId": 5,
  "categoryId": 12,
  "taxRate": 18,
  "deliveryOptions": { "minDeliveryDays": 1, "maxDeliveryDays": 5 },
  "images": [
    "https://cdn.ornek.com/tisort-1.jpg",
    "https://cdn.ornek.com/tisort-2.jpg"
  ],
  "variants": [
    {
      "barcode": "8691234567890",
      "stockCode": "TSRT-SYH-S",
      "stock": 25,
      "price": { "salePrice": 299.90, "listPrice": 449.90 },
      "attributes": [
        { "attributeId": 3, "attributeValueId": 15 },
        { "attributeId": 7, "attributeValueId": 41 }
      ]
    },
    {
      "barcode": "8691234567891",
      "stockCode": "TSRT-SYH-M",
      "stock": 30,
      "price": { "salePrice": 299.90, "listPrice": 449.90 },
      "attributes": [
        { "attributeId": 3, "attributeValueId": 15 },
        { "attributeId": 7, "attributeValueId": 42 }
      ]
    }
  ]
}

Yanıt (201)

{
  "contentId": 4567,
  "productMainId": "9876543210123",
  "status": "notOnSale",
  "title": "Pamuklu Basic Tişört",
  "brand": { "id": 5, "name": "Marka Adı" },
  "mainCategory": { "id": 7, "name": "Giyim" },
  "subCategory": { "id": 37, "name": "Tişört" },
  "category": { "id": 12, "name": "Basic Tişört", "leaf": true },
  "taxRate": 18,
  "variants": [
    { "name": "Siyah / S", "barcode": "8691234567890", "stockCode": "TSRT-SYH-S" },
    { "name": "Siyah / M", "barcode": "8691234567891", "stockCode": "TSRT-SYH-M" }
  ]
}
AlanAçıklama
contentIdMilagron sistemindeki ürün kaydı ID'si.
productMainIdÜrün ana kimliği. Ürün Listesi ucunda productMainId filtresi ile sorgulanabilir.
statusYeni ürün her zaman taslaktır ve notOnSale döner. Onay sürecinden sonra satışa alınır.
categoryÜrünün açıldığı yaprak kategori, yani istekteki categoryId. Üst seviyeler mainCategory ve subCategory alanlarında döner.
variants[].nameÖzellik değerlerinden üretilen varyant adı, örneğin "Siyah / S". Özellik kullanılmayan ürünlerde tek varyant oluşur ve adı Default Title olur.

İşlem Garantisi

Ürün oluşturma ya hep ya hiç ilkesiyle çalışır. 201 yanıtı, ürünün eksiksiz oluşturulduğu anlamına gelir. Herhangi bir adım başarısız olursa o ana kadar yapılan işlemler geri alınır ve hata yanıtı döner, yarım ürün oluşmaz. Hata yanıtı alan istekler güvenle yeniden denenebilir.

Doğrulama Kuralları

  • categoryId, kategori ağacının yaprak seviyesinden olmalıdır ("leaf": true); ara seviye ID'leri kabul edilmez.
  • taxRate, yaprak kategorinin izin verdiği oranlardan biri olmalıdır (kategori ağacındaki taxRates).
  • Aynı özellik değer kombinasyonu birden fazla varyantta kullanılamaz.
  • barcode ve stockCode, hem istek içinde hem sistem genelinde (mevcut ve onay bekleyen ürünler dahil) benzersiz olmalıdır.
  • Markanın komisyon oranı tanımlı olmalıdır.

Özellik Kuralları

Aşağıdaki kurallar GET .../categories/{categoryId}/attributes yanıtına göre uygulanır ve Milagron panelindeki ürün ekleme akışıyla birebir aynıdır.

  • Ürünün kullandığı özellikler varyantlardan türetilir; tüm varyantlar aynı attributeId kümesini bildirmelidir.
  • Her varyant, bildirdiği her özellik için geçerli bir attributeValueId vermelidir; değer ilgili özelliğe ait olmalıdır.
  • Kullanılan her attributeId, seçilen yaprak kategoriye atanmış ve variant: true olmalıdır.
  • required: true olan özelliklerin tamamı kullanılmalıdır.
  • multiple: false olan bir özellikte tüm varyantlar aynı attributeValueId'yi kullanmalıdır.
  • En fazla 3 özellik kullanılabilir.
  • Kategorinin zorunlu özelliği yoksa varyant attributes alanı boş bırakılabilir. Bu durumda yalnızca tek varyant gönderilebilir.
  • variantless: true olan kategorilerde özellik gönderilemez; ürün her zaman tek varyantlıdır.
  • Kategori için hiç özellik tanımlanmamışsa (boş attributes yanıtı ve variantless: false) ürün oluşturulamaz.

Tek Varyantlı Ürün Örneği

Kategorinin zorunlu özelliği yoksa özellik göndermeden tek varyantlı ürün oluşturulabilir:

{
  "title": "Seramik Vazo",
  "description": "<p>El yapımı seramik vazo.</p>",
  "brandId": 5,
  "categoryId": 31,
  "taxRate": 20,
  "deliveryOptions": { "minDeliveryDays": 1, "maxDeliveryDays": 3 },
  "images": ["https://cdn.ornek.com/vazo-1.jpg"],
  "variants": [
    {
      "barcode": "8691234567900",
      "stockCode": "VZO-001",
      "stock": 12,
      "price": { "salePrice": 499.90, "listPrice": 649.90 }
    }
  ]
}

Bu ürün tek varyantlı, yani seçeneksiz oluşur.

Hata Yanıtları

HTTPKodDurum
400BadRequestGeçersiz JSON gövdesi.
401 / 403Unauthorized / ForbiddenKimlik doğrulama, yetki veya satıcı eşleşme hatası.
404NotFoundSatıcı bulunamadı.
409ConflictBarkod veya SKU zaten kayıtlı.
422ValidationErrorAlan veya ID doğrulama hatası. Mesaj hangi alanın hatalı olduğunu belirtir.
429TooManyRequestsRate limit veya günlük varyant oluşturma limiti. Daha sonra tekrar deneyin.
500 / 502InternalError / UpstreamErrorSunucu tarafı hata. Ürün oluşmaz; istek güvenle yeniden denenebilir.

Kullanım Örnekleri

curl -u "API_KEY:API_SECRET" \
  -X POST "https://api.milagron.com/integration/product/sellers/123/products" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Pamuklu Basic Tişört",
    "description": "<p>%100 pamuk, rahat kesim.</p>",
    "brandId": 5,
    "categoryId": 12,
    "taxRate": 18,
    "deliveryOptions": {
        "minDeliveryDays": 1,
        "maxDeliveryDays": 5
    },
    "images": [
        "https://cdn.ornek.com/tisort-1.jpg"
    ],
    "variants": [
        {
            "barcode": "8691234567890",
            "stockCode": "TSRT-SYH-S",
            "stock": 25,
            "price": {
                "salePrice": 299.9,
                "listPrice": 449.9
            },
            "attributes": [
                {
                    "attributeId": 3,
                    "attributeValueId": 15
                },
                {
                    "attributeId": 7,
                    "attributeValueId": 41
                }
            ]
        }
    ]
}'
<?php

$ch = curl_init('https://api.milagron.com/integration/product/sellers/123/products');

curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERPWD        => 'API_KEY:API_SECRET',
    CURLOPT_CUSTOMREQUEST  => 'POST',
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => json_encode([
    'title' => 'Pamuklu Basic Tişört',
    'description' => '<p>%100 pamuk, rahat kesim.</p>',
    'brandId' => 5,
    'categoryId' => 12,
    'taxRate' => 18,
    'deliveryOptions' => [
        'minDeliveryDays' => 1,
        'maxDeliveryDays' => 5
    ],
    'images' => [
        'https://cdn.ornek.com/tisort-1.jpg'
    ],
    'variants' => [
        [
            'barcode' => '8691234567890',
            'stockCode' => 'TSRT-SYH-S',
            'stock' => 25,
            'price' => [
                'salePrice' => 299.9,
                'listPrice' => 449.9
            ],
            'attributes' => [
                [
                    'attributeId' => 3,
                    'attributeValueId' => 15
                ],
                [
                    'attributeId' => 7,
                    'attributeValueId' => 41
                ]
            ]
        ]
    ]
]),
]);

$response = curl_exec($ch);
$data = json_decode($response, true);
curl_close($ch);
const auth = Buffer.from('API_KEY:API_SECRET').toString('base64');

const res = await fetch('https://api.milagron.com/integration/product/sellers/123/products', {
    method: 'POST',
    headers: {
        'Authorization': `Basic ${auth}`,
        'Content-Type':  'application/json'
    },
    body: JSON.stringify({
    title: 'Pamuklu Basic Tişört',
    description: '<p>%100 pamuk, rahat kesim.</p>',
    brandId: 5,
    categoryId: 12,
    taxRate: 18,
    deliveryOptions: {
        minDeliveryDays: 1,
        maxDeliveryDays: 5
    },
    images: [
        'https://cdn.ornek.com/tisort-1.jpg'
    ],
    variants: [
        {
            barcode: '8691234567890',
            stockCode: 'TSRT-SYH-S',
            stock: 25,
            price: {
                salePrice: 299.9,
                listPrice: 449.9
            },
            attributes: [
                {
                    attributeId: 3,
                    attributeValueId: 15
                },
                {
                    attributeId: 7,
                    attributeValueId: 41
                }
            ]
        }
    ]
})
});

const data = await res.json();
import requests

response = requests.post(
    'https://api.milagron.com/integration/product/sellers/123/products',
    auth=('API_KEY', 'API_SECRET'),
    json={
    'title': 'Pamuklu Basic Tişört',
    'description': '<p>%100 pamuk, rahat kesim.</p>',
    'brandId': 5,
    'categoryId': 12,
    'taxRate': 18,
    'deliveryOptions': {
        'minDeliveryDays': 1,
        'maxDeliveryDays': 5
    },
    'images': [
        'https://cdn.ornek.com/tisort-1.jpg'
    ],
    'variants': [
        {
            'barcode': '8691234567890',
            'stockCode': 'TSRT-SYH-S',
            'stock': 25,
            'price': {
                'salePrice': 299.9,
                'listPrice': 449.9
            },
            'attributes': [
                {
                    'attributeId': 3,
                    'attributeValueId': 15
                },
                {
                    'attributeId': 7,
                    'attributeValueId': 41
                }
            ]
        }
    ]
}
)

response.raise_for_status()
data = response.json()
package main

import (
    "bytes"
    "encoding/json"
    "net/http"
)

func main() {
    payload, _ := json.Marshal(map[string]interface{}{
    "title": "Pamuklu Basic Tişört",
    "description": "<p>%100 pamuk, rahat kesim.</p>",
    "brandId": 5,
    "categoryId": 12,
    "taxRate": 18,
    "deliveryOptions": map[string]interface{}{
        "minDeliveryDays": 1,
        "maxDeliveryDays": 5,
    },
    "images": []interface{}{
        "https://cdn.ornek.com/tisort-1.jpg",
    },
    "variants": []interface{}{
        map[string]interface{}{
            "barcode": "8691234567890",
            "stockCode": "TSRT-SYH-S",
            "stock": 25,
            "price": map[string]interface{}{
                "salePrice": 299.9,
                "listPrice": 449.9,
            },
            "attributes": []interface{}{
                map[string]interface{}{
                    "attributeId": 3,
                    "attributeValueId": 15,
                },
                map[string]interface{}{
                    "attributeId": 7,
                    "attributeValueId": 41,
                },
            },
        },
    },
})
    req, _ := http.NewRequest("POST", "https://api.milagron.com/integration/product/sellers/123/products", bytes.NewBuffer(payload))
    req.SetBasicAuth("API_KEY", "API_SECRET")
    req.Header.Set("Content-Type", "application/json")

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()
}
import java.net.URI;
import java.net.http.*;
import java.util.Base64;

HttpClient client = HttpClient.newHttpClient();

String auth = Base64.getEncoder()
    .encodeToString("API_KEY:API_SECRET".getBytes());

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.milagron.com/integration/product/sellers/123/products"))
    .header("Authorization", "Basic " + auth)
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString("{\"title\":\"Pamuklu Basic Tişört\",\"description\":\"<p>%100 pamuk, rahat kesim.</p>\",\"brandId\":5,\"categoryId\":12,\"taxRate\":18,\"deliveryOptions\":{\"minDeliveryDays\":1,\"maxDeliveryDays\":5},\"images\":[\"https://cdn.ornek.com/tisort-1.jpg\"],\"variants\":[{\"barcode\":\"8691234567890\",\"stockCode\":\"TSRT-SYH-S\",\"stock\":25,\"price\":{\"salePrice\":299.9,\"listPrice\":449.9},\"attributes\":[{\"attributeId\":3,\"attributeValueId\":15},{\"attributeId\":7,\"attributeValueId\":41}]}]}"))
    .build();

HttpResponse<String> response = client.send(request,
    HttpResponse.BodyHandlers.ofString());
require 'net/http'
require 'uri'
require 'json'

uri = URI('https://api.milagron.com/integration/product/sellers/123/products')

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Post.new(uri.request_uri)
request.basic_auth('API_KEY', 'API_SECRET')
request['Content-Type'] = 'application/json'
request.body = {
  title: 'Pamuklu Basic Tişört',
  description: '<p>%100 pamuk, rahat kesim.</p>',
  brandId: 5,
  categoryId: 12,
  taxRate: 18,
  deliveryOptions: {
    minDeliveryDays: 1,
    maxDeliveryDays: 5
  },
  images: [
    'https://cdn.ornek.com/tisort-1.jpg'
  ],
  variants: [
    {
      barcode: '8691234567890',
      stockCode: 'TSRT-SYH-S',
      stock: 25,
      price: {
        salePrice: 299.9,
        listPrice: 449.9
      },
      attributes: [
        {
          attributeId: 3,
          attributeValueId: 15
        },
        {
          attributeId: 7,
          attributeValueId: 41
        }
      ]
    }
  ]
}.to_json

response = http.request(request)
data = JSON.parse(response.body)
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;

var client = new HttpClient();

var auth = Convert.ToBase64String(
    Encoding.UTF8.GetBytes("API_KEY:API_SECRET"));
client.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Basic", auth);

var content = new StringContent(
    "{\"title\":\"Pamuklu Basic Tişört\",\"description\":\"<p>%100 pamuk, rahat kesim.</p>\",\"brandId\":5,\"categoryId\":12,\"taxRate\":18,\"deliveryOptions\":{\"minDeliveryDays\":1,\"maxDeliveryDays\":5},\"images\":[\"https://cdn.ornek.com/tisort-1.jpg\"],\"variants\":[{\"barcode\":\"8691234567890\",\"stockCode\":\"TSRT-SYH-S\",\"stock\":25,\"price\":{\"salePrice\":299.9,\"listPrice\":449.9},\"attributes\":[{\"attributeId\":3,\"attributeValueId\":15},{\"attributeId\":7,\"attributeValueId\":41}]}]}",
    Encoding.UTF8,
    "application/json");

var response = await client.PostAsync("https://api.milagron.com/integration/product/sellers/123/products", content);
var data = await response.Content.ReadAsStringAsync();

Notlar

  • Ürün taslak olarak oluşur; satışa çıkışını Milagron onay süreci belirler.
  • Doğrulama kuralları Milagron panelindeki ürün ekleme ekranıyla aynıdır; API'den ve panelden oluşturulan ürünler aynı onay sürecine girer.
  • Görseller verilen URL'lerden indirilir; URL'ler herkese açık erişilebilir olmalıdır.
  • Stok ve fiyat güncellemeleri için Stok-Fiyat Güncelleme ucunu kullanın.
  • Stage ortamında tüm doğrulamalar çalışır; ürün oluşturulmaz, _simulated işaretli yanıt döner.