Ürün Oluşturma

Mağazaya yeni ürün ekler. Ürün taslak (DRAFT) olarak oluşturulur; yayına alma 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
https://stageapi.milagron.com/integration/product/sellers/{sellerId}/products
ID tabanlı referanslar: Marka, kategori, ürün tipi ve özellik (attribute) alanlarının tamamı isim değil ID ile gönderilir. Geçerli ID'leri Katalog & ID Keşfi endpoint'lerinden alı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.
mainCategoryIdintegerEvetAna kategori ID'si. GET .../categories ile alınır.
subCategoryIdintegerEvetAlt kategori ID'si. Seçilen ana kategorinin alt kategorisi olmalıdır.
productTypeIdintegerEvetÜrün tipi ID'si. GET .../product-types?subCategoryId=... ile alınır; seçilen alt kategoriye ait olmalıdır.
taxRateintegerEvetKDV oranı. Ürün tipinin 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.
attributesarray<integer>HayırSıralı özellik (attribute) ID listesi, en fazla 3. Sıra, varyant adını belirler (ör. "Siyah / S"). Boşsa ürün tek varyantlı olmalıdır.
variantsarrayEvetVaryant listesi (en az 1, en fazla 100). 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.
costnumberHayırAlış maliyeti (vitrine yansımaz, raporlama içindir).
attributesarrayKoşulluÜründe bildirilen her attribute için { "attributeId": x, "attributeValueId": y }. Üründe attribute varsa zorunludur.

Örnek İstek

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

Yanıt (201)

{
  "contentId": 4567,
  "productMainId": "9876543210123",
  "status": "DRAFT",
  "title": "Pamuklu Basic Tişört",
  "brand": { "id": 5, "name": "Marka Adı" },
  "category": { "id": 7, "name": "Giyim" },
  "subCategory": { "id": 37, "name": "Tişört" },
  "productType": { "id": 12, "name": "Tişört" },
  "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 endpoint'inde productMainId filtresi ile sorgulanabilir.
statusHer zaman DRAFT. Ürün, onay sürecinden sonra yayına alınır.

İş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ı

  • subCategoryId, mainCategoryId'nin alt kategorisi olmalıdır.
  • productTypeId, seçilen alt kategoriye ait olmalıdır.
  • taxRate, ürün tipinin izin verdiği oranlardan biri olmalıdır (GET .../product-types yanıtındaki taxRates).
  • Her varyant, üründe bildirilen tüm attribute'lar için geçerli bir attributeValueId içermelidir; değer ilgili attribute'a ait olmalıdır.
  • Aynı attribute 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.
  • attributes boş bırakılırsa yalnızca tek varyant gönderilebilir.

Hata Yanıtları

HTTPKodDurum
400BadRequestGeçersiz JSON gövdesi.
401 / 403Unauthorized / ForbiddenKimlik doğrulama, yetki (scope) veya satıcı eşleşme hatası.
404NotFoundSatıcı bulunamadı.
409ConflictBarkod veya SKU zaten kayıtlı.
422ValidationErrorAlan/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,
    "mainCategoryId": 7,
    "subCategoryId": 37,
    "productTypeId": 12,
    "taxRate": 18,
    "deliveryOptions": {
        "minDeliveryDays": 1,
        "maxDeliveryDays": 5
    },
    "images": [
        "https://cdn.ornek.com/tisort-1.jpg"
    ],
    "attributes": [
        3,
        7
    ],
    "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,
    'mainCategoryId' => 7,
    'subCategoryId' => 37,
    'productTypeId' => 12,
    'taxRate' => 18,
    'deliveryOptions' => [
        'minDeliveryDays' => 1,
        'maxDeliveryDays' => 5
    ],
    'images' => [
        'https://cdn.ornek.com/tisort-1.jpg'
    ],
    'attributes' => [
        3,
        7
    ],
    '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,
    mainCategoryId: 7,
    subCategoryId: 37,
    productTypeId: 12,
    taxRate: 18,
    deliveryOptions: {
        minDeliveryDays: 1,
        maxDeliveryDays: 5
    },
    images: [
        'https://cdn.ornek.com/tisort-1.jpg'
    ],
    attributes: [
        3,
        7
    ],
    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,
    'mainCategoryId': 7,
    'subCategoryId': 37,
    'productTypeId': 12,
    'taxRate': 18,
    'deliveryOptions': {
        'minDeliveryDays': 1,
        'maxDeliveryDays': 5
    },
    'images': [
        'https://cdn.ornek.com/tisort-1.jpg'
    ],
    'attributes': [
        3,
        7
    ],
    '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,
    "mainCategoryId": 7,
    "subCategoryId": 37,
    "productTypeId": 12,
    "taxRate": 18,
    "deliveryOptions": map[string]interface{}{
        "minDeliveryDays": 1,
        "maxDeliveryDays": 5,
    },
    "images": []interface{}{
        "https://cdn.ornek.com/tisort-1.jpg",
    },
    "attributes": []interface{}{
        3,
        7,
    },
    "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,\"mainCategoryId\":7,\"subCategoryId\":37,\"productTypeId\":12,\"taxRate\":18,\"deliveryOptions\":{\"minDeliveryDays\":1,\"maxDeliveryDays\":5},\"images\":[\"https://cdn.ornek.com/tisort-1.jpg\"],\"attributes\":[3,7],\"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,
  mainCategoryId: 7,
  subCategoryId: 37,
  productTypeId: 12,
  taxRate: 18,
  deliveryOptions: {
    minDeliveryDays: 1,
    maxDeliveryDays: 5
  },
  images: [
    'https://cdn.ornek.com/tisort-1.jpg'
  ],
  attributes: [
    3,
    7
  ],
  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,\"mainCategoryId\":7,\"subCategoryId\":37,\"productTypeId\":12,\"taxRate\":18,\"deliveryOptions\":{\"minDeliveryDays\":1,\"maxDeliveryDays\":5},\"images\":[\"https://cdn.ornek.com/tisort-1.jpg\"],\"attributes\":[3,7],\"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 DRAFT (taslak) olarak oluşturulur; vitrine çıkışı Milagron onay süreci belirler.
  • 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 endpoint'ini kullanın.
  • Stage ortamında tüm doğrulamalar çalışır; ürün oluşturulmaz, _simulated işaretli yanıt döner.