{
  "info": {
    "_postman_id": "9f2c1b7e-4d3a-4c58-9c21-5f6a1e0b74d2",
    "name": "Lydira · Import API",
    "description": "# Lydira · Aktarım API'si / Import API\n\nBilet, otel, transfer, cruise, araç kiralama, müşteri, tedarikçi ve devir\nbelgelerinizi JSON ile Lydira'ya aktarın. Dosya yükleme sihirbazıyla\n(`/settings/imports`) **aynı motoru** kullanır; fark, JSON'un iç içe\nveriyi (fiyat satırları, yolcular, uçuş bacakları) taşıyabilmesidir.\n\nImport tickets, hotel stays, transfers, cruises, car rentals, people and\nbrought-forward documents as JSON. It runs the **same engine** as the file\nwizard at `/settings/imports`; the difference is that JSON can carry the\nnested detail — pricing lines, travellers, flight legs — a spreadsheet cell\ncannot.\n\n## Başlarken / Getting started\n\n1. Lydira'da **Ayarlar → API anahtarları**'ndan `import` kapsamlı bir\n   anahtar oluşturun (yalnızca bir kez gösterilir).\n2. Bu koleksiyonun ortam dosyasını (`…postman_environment.json`) içe\n   aktarın ve `api_key` ile `base_url` değerlerini doldurun.\n3. **0 · Başlangıç** klasöründeki isteklerle bağlantıyı doğrulayın.\n4. Klasörleri sırayla çalıştırın — sıra bilinçlidir: rezervasyonlar\n   müşteri ve tedarikçilere bağlanır.\n\n## Üç kural / Three rules\n\n- **`external_id` zorunludur.** Kaynak sistemdeki kendi kimliğiniz. Aynı\n  isteği tekrar göndermek asla kopya üretmez: kişiler ve belgeler\n  güncellenir, rezervasyonlar atlanır.\n- **Deneme = gerçek.** `…/validate` hiçbir şey yazmadan tam olarak aynı\n  yolu koşar.\n- **Bozuk satır tek başına düşer.** Partinin geri kalanı içeri girer;\n  hata alan satır sebebiyle birlikte raporlanır.\n\n- **`external_id` is required** — your own key in the source system.\n  Re-sending never duplicates: people and documents update, bookings skip.\n- **Dry-run ≡ commit.** `…/validate` runs the identical path, persisting\n  nothing.\n- **A bad row fails alone.** The rest of the batch still imports.\n\n> Bu dosya otomatik üretilir — elle düzenlemeyin, bir sonraki sürümde\n> üzerine yazılır. Güncel hâlini her zaman Lydira'da **Ayarlar → API\n> anahtarları** sayfasından indirebilirsiniz.\n>\n> Generated automatically — don't hand-edit it; the next release overwrites\n> it. Always re-download the current one from **Settings → API keys**.\n",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "bearer",
    "bearer": [
      {
        "key": "token",
        "value": "{{api_key}}",
        "type": "string"
      }
    ]
  },
  "event": [
    {
      "listen": "test",
      "script": {
        "type": "text/javascript",
        "exec": [
          "pm.test(\"kimlik doğrulandı / authenticated\", function () {",
          "  if (pm.response.code === 401) {",
          "    throw new Error(\"401 — {{api_key}} boş ya da geçersiz. Ayarlar → API anahtarları'ndan `import` kapsamlı bir anahtar oluşturun. / Create an `import`-scoped key under Settings → API keys.\");",
          "  }",
          "  if (pm.response.code === 403 && pm.response.json().code === \"plan_upgrade_required\") {",
          "    throw new Error(\"403 — planınız API erişimi içermiyor. / Your plan does not include API access.\");",
          "  }",
          "});"
        ]
      }
    }
  ],
  "variable": [
    {
      "key": "base_url",
      "value": "http://localhost:3000",
      "type": "string"
    },
    {
      "key": "source_system",
      "value": "postman",
      "type": "string"
    },
    {
      "key": "import_id",
      "value": "",
      "type": "string"
    }
  ],
  "item": [
    {
      "name": "0 · Başlangıç / Getting started",
      "item": [
        {
          "name": "Sağlık kontrolü / Health check",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/v1/health",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "health"
              ]
            },
            "description": "Anahtarın çalıştığını doğrular. 401 alırsanız `api_key` değişkenini,\n403 alırsanız planınızın API erişimini kontrol edin.\n\nConfirms the key works. A 401 means the `api_key` variable; a 403 means\nyour plan doesn't include API access."
          }
        },
        {
          "name": "Neler aktarılabilir? / What can be imported?",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/entities",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "entities"
              ]
            },
            "description": "Aktarılabilir kayıt tiplerinin kataloğu — her biri için eşsizlik\n(idempotency) kuralı ve uç noktalar.\n\nThe catalogue of importable entities, each with its idempotency rule\nand endpoints."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200 OK\", () => pm.response.to.have.status(200));",
                  "pm.test(\"katalog dolu / catalogue is populated\", () =>",
                  "  pm.expect(pm.response.json().data.length).to.be.above(0));"
                ]
              }
            }
          ]
        },
        {
          "name": "Bir tipin şeması / One entity's schema",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/entities/tickets",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "entities",
                "tickets"
              ]
            },
            "description": "Tek bir tipin tüm alanları, iç içe yapıları ve **doğrudan\ngönderilebilir bir örnek gövde** (`entity.sample`).\n\nEvery field of one entity, its nested shapes, and a **ready-to-POST\nsample body** (`entity.sample`)."
          }
        }
      ]
    },
    {
      "name": "1 · Kişiler / People",
      "item": [
        {
          "name": "Customers · deneme (dry-run)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/customers/validate",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "customers",
                "validate"
              ]
            },
            "description": "Hiçbir şey yazmaz. Gerçek aktarımla **birebir aynı** yolu çalıştırır\n(rezervasyon gerçekten kurulur, sonra geri alınır), bu yüzden burada yeşil\nolan aktarımda patlamaz.\n\nWrites nothing. Runs the **identical** path the real import runs\n(a booking really is built, then thrown away), so green here cannot explode\non commit.\n\n**Zorunlu / Required:** `external_id`, `name`",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source_system\": \"{{source_system}}\",\n  \"rows\": [\n    {\n      \"external_id\": \"CUSTOMER-1001\",\n      \"name\": \"Ada Lovelace\",\n      \"customer_type\": \"individual\",\n      \"email\": \"ada@example.com\",\n      \"phone\": \"+905551112233\",\n      \"legal_name\": \"Lovelace Seyahat A.Ş.\",\n      \"tax_office\": \"Beşiktaş\",\n      \"address_line\": \"Nispetiye Cad. No:12\",\n      \"address_district\": \"Beşiktaş\",\n      \"address_city\": \"İstanbul\",\n      \"address_state\": \"\",\n      \"address_zip\": \"34340\",\n      \"preferred_currency\": \"EUR\",\n      \"code\": \"AC-1001\",\n      \"notes\": \"Imported from the source system.\"\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200 OK\", () => pm.response.to.have.status(200));",
                  "pm.test(\"geçerli / valid\", () =>",
                  "  pm.expect(pm.response.json().import.stats.invalid).to.eql(0));"
                ]
              }
            }
          ]
        },
        {
          "name": "Customers · aktar (import)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/customers",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "customers"
              ]
            },
            "description": "Aynı `external_id` ile ikinci kez gönderirseniz kayıt **güncellenir**\n(`updated`), kopyalanmaz.\n\nSending the same `external_id` again **updates** the record, never\nduplicates it.\n\nYanıttaki `results[].record.id` oluşan Lydira kaydının kimliğidir.\n`import.id` otomatik olarak `{{import_id}}` değişkenine yazılır.\n\n`results[].record.id` is the Lydira record; `import.id` is stored into\nthe `{{import_id}}` variable automatically.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source_system\": \"{{source_system}}\",\n  \"rows\": [\n    {\n      \"external_id\": \"CUSTOMER-1001\",\n      \"name\": \"Ada Lovelace\",\n      \"customer_type\": \"individual\",\n      \"email\": \"ada@example.com\",\n      \"phone\": \"+905551112233\",\n      \"legal_name\": \"Lovelace Seyahat A.Ş.\",\n      \"tax_office\": \"Beşiktaş\",\n      \"address_line\": \"Nispetiye Cad. No:12\",\n      \"address_district\": \"Beşiktaş\",\n      \"address_city\": \"İstanbul\",\n      \"address_state\": \"\",\n      \"address_zip\": \"34340\",\n      \"preferred_currency\": \"EUR\",\n      \"code\": \"AC-1001\",\n      \"notes\": \"Imported from the source system.\"\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"201 ya da 200 / created or idempotent\", () =>",
                  "  pm.expect(pm.response.code).to.be.oneOf([200, 201]));",
                  "pm.collectionVariables.set(\"import_id\", pm.response.json().import.id);",
                  "pm.test(\"hiç hata yok / no errors\", () => {",
                  "  const s = pm.response.json().import.stats;",
                  "  pm.expect(s.invalid + s.failed).to.eql(0);",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "Suppliers · deneme (dry-run)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/suppliers/validate",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "suppliers",
                "validate"
              ]
            },
            "description": "Hiçbir şey yazmaz. Gerçek aktarımla **birebir aynı** yolu çalıştırır\n(rezervasyon gerçekten kurulur, sonra geri alınır), bu yüzden burada yeşil\nolan aktarımda patlamaz.\n\nWrites nothing. Runs the **identical** path the real import runs\n(a booking really is built, then thrown away), so green here cannot explode\non commit.\n\n**Zorunlu / Required:** `external_id`, `name`",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source_system\": \"{{source_system}}\",\n  \"rows\": [\n    {\n      \"external_id\": \"SUPPLIER-1001\",\n      \"name\": \"Ada Lovelace\",\n      \"supplier_type\": \"hotel\",\n      \"code\": \"AC-1001\",\n      \"iata_code\": \"TK\",\n      \"email\": \"ada@example.com\",\n      \"phone\": \"+905551112233\",\n      \"country_code\": \"TR\",\n      \"tax_office\": \"Beşiktaş\",\n      \"address_line\": \"Nispetiye Cad. No:12\",\n      \"address_district\": \"Beşiktaş\",\n      \"address_city\": \"İstanbul\",\n      \"address_state\": \"\",\n      \"address_zip\": \"34340\",\n      \"website\": \"https://example.com\"\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200 OK\", () => pm.response.to.have.status(200));",
                  "pm.test(\"geçerli / valid\", () =>",
                  "  pm.expect(pm.response.json().import.stats.invalid).to.eql(0));"
                ]
              }
            }
          ]
        },
        {
          "name": "Suppliers · aktar (import)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/suppliers",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "suppliers"
              ]
            },
            "description": "Aynı `external_id` ile ikinci kez gönderirseniz kayıt **güncellenir**\n(`updated`), kopyalanmaz.\n\nSending the same `external_id` again **updates** the record, never\nduplicates it.\n\nYanıttaki `results[].record.id` oluşan Lydira kaydının kimliğidir.\n`import.id` otomatik olarak `{{import_id}}` değişkenine yazılır.\n\n`results[].record.id` is the Lydira record; `import.id` is stored into\nthe `{{import_id}}` variable automatically.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source_system\": \"{{source_system}}\",\n  \"rows\": [\n    {\n      \"external_id\": \"SUPPLIER-1001\",\n      \"name\": \"Ada Lovelace\",\n      \"supplier_type\": \"hotel\",\n      \"code\": \"AC-1001\",\n      \"iata_code\": \"TK\",\n      \"email\": \"ada@example.com\",\n      \"phone\": \"+905551112233\",\n      \"country_code\": \"TR\",\n      \"tax_office\": \"Beşiktaş\",\n      \"address_line\": \"Nispetiye Cad. No:12\",\n      \"address_district\": \"Beşiktaş\",\n      \"address_city\": \"İstanbul\",\n      \"address_state\": \"\",\n      \"address_zip\": \"34340\",\n      \"website\": \"https://example.com\"\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"201 ya da 200 / created or idempotent\", () =>",
                  "  pm.expect(pm.response.code).to.be.oneOf([200, 201]));",
                  "pm.collectionVariables.set(\"import_id\", pm.response.json().import.id);",
                  "pm.test(\"hiç hata yok / no errors\", () => {",
                  "  const s = pm.response.json().import.stats;",
                  "  pm.expect(s.invalid + s.failed).to.eql(0);",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "Leads · deneme (dry-run)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/leads/validate",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "leads",
                "validate"
              ]
            },
            "description": "Hiçbir şey yazmaz. Gerçek aktarımla **birebir aynı** yolu çalıştırır\n(rezervasyon gerçekten kurulur, sonra geri alınır), bu yüzden burada yeşil\nolan aktarımda patlamaz.\n\nWrites nothing. Runs the **identical** path the real import runs\n(a booking really is built, then thrown away), so green here cannot explode\non commit.\n\n**Zorunlu / Required:** `external_id`, `name`\n\n**Bağlantılar / References:** `customer_external_id` → customers (skip)",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source_system\": \"{{source_system}}\",\n  \"rows\": [\n    {\n      \"external_id\": \"LEAD-1001\",\n      \"name\": \"Ada Lovelace\",\n      \"email\": \"ada@example.com\",\n      \"phone\": \"+905551112233\",\n      \"stage\": \"inbox\",\n      \"source\": \"website_form\",\n      \"estimated_value\": \"1250.00\",\n      \"currency\": \"EUR\",\n      \"party_size\": 2,\n      \"destinations\": \"Roma, Floransa\",\n      \"customer_external_id\": \"CUSTOMER-1001\",\n      \"notes\": \"Imported from the source system.\"\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200 OK\", () => pm.response.to.have.status(200));",
                  "pm.test(\"geçerli / valid\", () =>",
                  "  pm.expect(pm.response.json().import.stats.invalid).to.eql(0));"
                ]
              }
            }
          ]
        },
        {
          "name": "Leads · aktar (import)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/leads",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "leads"
              ]
            },
            "description": "Aynı `external_id` ile ikinci kez gönderirseniz kayıt **güncellenir**\n(`updated`), kopyalanmaz.\n\nSending the same `external_id` again **updates** the record, never\nduplicates it.\n\nYanıttaki `results[].record.id` oluşan Lydira kaydının kimliğidir.\n`import.id` otomatik olarak `{{import_id}}` değişkenine yazılır.\n\n`results[].record.id` is the Lydira record; `import.id` is stored into\nthe `{{import_id}}` variable automatically.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source_system\": \"{{source_system}}\",\n  \"rows\": [\n    {\n      \"external_id\": \"LEAD-1001\",\n      \"name\": \"Ada Lovelace\",\n      \"email\": \"ada@example.com\",\n      \"phone\": \"+905551112233\",\n      \"stage\": \"inbox\",\n      \"source\": \"website_form\",\n      \"estimated_value\": \"1250.00\",\n      \"currency\": \"EUR\",\n      \"party_size\": 2,\n      \"destinations\": \"Roma, Floransa\",\n      \"customer_external_id\": \"CUSTOMER-1001\",\n      \"notes\": \"Imported from the source system.\"\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"201 ya da 200 / created or idempotent\", () =>",
                  "  pm.expect(pm.response.code).to.be.oneOf([200, 201]));",
                  "pm.collectionVariables.set(\"import_id\", pm.response.json().import.id);",
                  "pm.test(\"hiç hata yok / no errors\", () => {",
                  "  const s = pm.response.json().import.stats;",
                  "  pm.expect(s.invalid + s.failed).to.eql(0);",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "Tour departures · deneme (dry-run)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/tour_departures/validate",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "tour_departures",
                "validate"
              ]
            },
            "description": "Hiçbir şey yazmaz. Gerçek aktarımla **birebir aynı** yolu çalıştırır\n(rezervasyon gerçekten kurulur, sonra geri alınır), bu yüzden burada yeşil\nolan aktarımda patlamaz.\n\nWrites nothing. Runs the **identical** path the real import runs\n(a booking really is built, then thrown away), so green here cannot explode\non commit.\n\n**Zorunlu / Required:** `external_id`, `title`\n\n**Bağlantılar / References:** `supplier_external_id` → suppliers (skip)",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source_system\": \"{{source_system}}\",\n  \"rows\": [\n    {\n      \"external_id\": \"TOUR-DEPARTURE-1001\",\n      \"title\": \"Title\",\n      \"starts_on\": \"2026-03-14\",\n      \"ends_on\": \"2026-03-18\",\n      \"currency\": \"EUR\",\n      \"max_capacity\": 2,\n      \"inventory_state\": \"open\",\n      \"notes\": \"Imported from the source system.\",\n      \"supplier_external_id\": \"SUPPLIER-1001\"\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200 OK\", () => pm.response.to.have.status(200));",
                  "pm.test(\"geçerli / valid\", () =>",
                  "  pm.expect(pm.response.json().import.stats.invalid).to.eql(0));"
                ]
              }
            }
          ]
        },
        {
          "name": "Tour departures · aktar (import)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/tour_departures",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "tour_departures"
              ]
            },
            "description": "Aynı `external_id` ile ikinci kez gönderirseniz kayıt **güncellenir**\n(`updated`), kopyalanmaz.\n\nSending the same `external_id` again **updates** the record, never\nduplicates it.\n\nYanıttaki `results[].record.id` oluşan Lydira kaydının kimliğidir.\n`import.id` otomatik olarak `{{import_id}}` değişkenine yazılır.\n\n`results[].record.id` is the Lydira record; `import.id` is stored into\nthe `{{import_id}}` variable automatically.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source_system\": \"{{source_system}}\",\n  \"rows\": [\n    {\n      \"external_id\": \"TOUR-DEPARTURE-1001\",\n      \"title\": \"Title\",\n      \"starts_on\": \"2026-03-14\",\n      \"ends_on\": \"2026-03-18\",\n      \"currency\": \"EUR\",\n      \"max_capacity\": 2,\n      \"inventory_state\": \"open\",\n      \"notes\": \"Imported from the source system.\",\n      \"supplier_external_id\": \"SUPPLIER-1001\"\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"201 ya da 200 / created or idempotent\", () =>",
                  "  pm.expect(pm.response.code).to.be.oneOf([200, 201]));",
                  "pm.collectionVariables.set(\"import_id\", pm.response.json().import.id);",
                  "pm.test(\"hiç hata yok / no errors\", () => {",
                  "  const s = pm.response.json().import.stats;",
                  "  pm.expect(s.invalid + s.failed).to.eql(0);",
                  "});"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "2 · Rezervasyonlar / Bookings",
      "item": [
        {
          "name": "Tickets · deneme (dry-run)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/tickets/validate",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "tickets",
                "validate"
              ]
            },
            "description": "Hiçbir şey yazmaz. Gerçek aktarımla **birebir aynı** yolu çalıştırır\n(rezervasyon gerçekten kurulur, sonra geri alınır), bu yüzden burada yeşil\nolan aktarımda patlamaz.\n\nWrites nothing. Runs the **identical** path the real import runs\n(a booking really is built, then thrown away), so green here cannot explode\non commit.\n\n**Zorunlu / Required:** `external_id`, `passengers`\n\n**Bağlantılar / References:** `customer_external_id` → customers (skip) · `supplier_external_id` → suppliers (skip)",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source_system\": \"{{source_system}}\",\n  \"rows\": [\n    {\n      \"external_id\": \"TICKET-1001\",\n      \"pnr\": \"ABC123\",\n      \"gds_pnr\": \"ABC123\",\n      \"currency\": \"EUR\",\n      \"settlement_channel\": \"bsp\",\n      \"fare_type\": \"normal\",\n      \"miles_used\": 2,\n      \"reservation_giver_name\": \"Ada Lovelace\",\n      \"issuing_system\": \"amadeus\",\n      \"option_date\": \"2026-03-14\",\n      \"transaction_date\": \"2026-03-14\",\n      \"invoice_date\": \"2026-03-18\",\n      \"notes\": \"Imported from the source system.\",\n      \"legs\": [\n        {\n          \"airline_code\": \"TK\",\n          \"flight_number\": \"1985\",\n          \"departure_airport\": \"IST\",\n          \"arrival_airport\": \"FCO\",\n          \"departure_at\": \"2026-03-14T09:30:00+03:00\",\n          \"arrival_at\": \"2026-03-14T12:45:00+03:00\",\n          \"cabin_class\": \"economy\",\n          \"booking_class\": \"L\",\n          \"fare_basis\": \"LLXOW\",\n          \"baggage_allowance\": \"1PC\",\n          \"status\": \"confirmed\"\n        }\n      ],\n      \"passengers\": [\n        {\n          \"first_name\": \"Ada\",\n          \"last_name\": \"Lovelace\",\n          \"nationality\": \"TR\",\n          \"national_id\": \"10000000146\",\n          \"passport_number\": \"U01234567\",\n          \"passport_country\": \"TR\",\n          \"passport_expiry\": \"2031-06-30\",\n          \"date_of_birth\": \"1988-04-21\",\n          \"gender\": \"female\",\n          \"frequent_flyer_number\": \"TK123456789\",\n          \"name\": \"Ada Lovelace\",\n          \"type\": \"adult\",\n          \"ticket_number\": \"235-1234567890\",\n          \"cost_lines\": [\n            {\n              \"kind\": \"base_fare\",\n              \"amount\": \"1250.00\",\n              \"label\": \"Imported line\",\n              \"currency\": \"EUR\",\n              \"vat_rate\": \"20\",\n              \"tax_inclusive\": true,\n              \"quantity\": 1\n            }\n          ],\n          \"sell_lines\": [\n            {\n              \"kind\": \"package_price\",\n              \"amount\": \"1250.00\",\n              \"label\": \"Imported line\",\n              \"currency\": \"EUR\",\n              \"vat_rate\": \"20\",\n              \"tax_inclusive\": true,\n              \"quantity\": 1\n            }\n          ]\n        }\n      ],\n      \"customer_external_id\": \"CUSTOMER-1001\",\n      \"supplier_external_id\": \"SUPPLIER-1001\"\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200 OK\", () => pm.response.to.have.status(200));",
                  "pm.test(\"geçerli / valid\", () =>",
                  "  pm.expect(pm.response.json().import.stats.invalid).to.eql(0));"
                ]
              }
            }
          ]
        },
        {
          "name": "Tickets · aktar (import)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/tickets",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "tickets"
              ]
            },
            "description": "Aynı `external_id` ile ikinci kez gönderirseniz satır **atlanır**\n(`skipped`) — rezervasyonlar bir kez oluşturulur.\n\nSending the same `external_id` again **skips** the row — bookings are\ncreate-once.\n\nYanıttaki `results[].record.id` oluşan Lydira kaydının kimliğidir.\n`import.id` otomatik olarak `{{import_id}}` değişkenine yazılır.\n\n`results[].record.id` is the Lydira record; `import.id` is stored into\nthe `{{import_id}}` variable automatically.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source_system\": \"{{source_system}}\",\n  \"rows\": [\n    {\n      \"external_id\": \"TICKET-1001\",\n      \"pnr\": \"ABC123\",\n      \"gds_pnr\": \"ABC123\",\n      \"currency\": \"EUR\",\n      \"settlement_channel\": \"bsp\",\n      \"fare_type\": \"normal\",\n      \"miles_used\": 2,\n      \"reservation_giver_name\": \"Ada Lovelace\",\n      \"issuing_system\": \"amadeus\",\n      \"option_date\": \"2026-03-14\",\n      \"transaction_date\": \"2026-03-14\",\n      \"invoice_date\": \"2026-03-18\",\n      \"notes\": \"Imported from the source system.\",\n      \"legs\": [\n        {\n          \"airline_code\": \"TK\",\n          \"flight_number\": \"1985\",\n          \"departure_airport\": \"IST\",\n          \"arrival_airport\": \"FCO\",\n          \"departure_at\": \"2026-03-14T09:30:00+03:00\",\n          \"arrival_at\": \"2026-03-14T12:45:00+03:00\",\n          \"cabin_class\": \"economy\",\n          \"booking_class\": \"L\",\n          \"fare_basis\": \"LLXOW\",\n          \"baggage_allowance\": \"1PC\",\n          \"status\": \"confirmed\"\n        }\n      ],\n      \"passengers\": [\n        {\n          \"first_name\": \"Ada\",\n          \"last_name\": \"Lovelace\",\n          \"nationality\": \"TR\",\n          \"national_id\": \"10000000146\",\n          \"passport_number\": \"U01234567\",\n          \"passport_country\": \"TR\",\n          \"passport_expiry\": \"2031-06-30\",\n          \"date_of_birth\": \"1988-04-21\",\n          \"gender\": \"female\",\n          \"frequent_flyer_number\": \"TK123456789\",\n          \"name\": \"Ada Lovelace\",\n          \"type\": \"adult\",\n          \"ticket_number\": \"235-1234567890\",\n          \"cost_lines\": [\n            {\n              \"kind\": \"base_fare\",\n              \"amount\": \"1250.00\",\n              \"label\": \"Imported line\",\n              \"currency\": \"EUR\",\n              \"vat_rate\": \"20\",\n              \"tax_inclusive\": true,\n              \"quantity\": 1\n            }\n          ],\n          \"sell_lines\": [\n            {\n              \"kind\": \"package_price\",\n              \"amount\": \"1250.00\",\n              \"label\": \"Imported line\",\n              \"currency\": \"EUR\",\n              \"vat_rate\": \"20\",\n              \"tax_inclusive\": true,\n              \"quantity\": 1\n            }\n          ]\n        }\n      ],\n      \"customer_external_id\": \"CUSTOMER-1001\",\n      \"supplier_external_id\": \"SUPPLIER-1001\"\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"201 ya da 200 / created or idempotent\", () =>",
                  "  pm.expect(pm.response.code).to.be.oneOf([200, 201]));",
                  "pm.collectionVariables.set(\"import_id\", pm.response.json().import.id);",
                  "pm.test(\"hiç hata yok / no errors\", () => {",
                  "  const s = pm.response.json().import.stats;",
                  "  pm.expect(s.invalid + s.failed).to.eql(0);",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "Hotel stays · deneme (dry-run)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/hotel_stays/validate",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "hotel_stays",
                "validate"
              ]
            },
            "description": "Hiçbir şey yazmaz. Gerçek aktarımla **birebir aynı** yolu çalıştırır\n(rezervasyon gerçekten kurulur, sonra geri alınır), bu yüzden burada yeşil\nolan aktarımda patlamaz.\n\nWrites nothing. Runs the **identical** path the real import runs\n(a booking really is built, then thrown away), so green here cannot explode\non commit.\n\n**Zorunlu / Required:** `external_id`, `check_in_on`, `check_out_on`\n\n**Bağlantılar / References:** `customer_external_id` → customers (skip) · `supplier_external_id` → suppliers (skip)",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source_system\": \"{{source_system}}\",\n  \"rows\": [\n    {\n      \"external_id\": \"HOTEL-STAY-1001\",\n      \"check_in_on\": \"2026-03-14\",\n      \"check_out_on\": \"2026-03-18\",\n      \"currency\": \"EUR\",\n      \"guest_count\": 2,\n      \"customer_external_id\": \"CUSTOMER-1001\",\n      \"supplier_external_id\": \"SUPPLIER-1001\",\n      \"status\": \"draft\",\n      \"notes\": \"Imported from the source system.\",\n      \"rate_basis\": \"net\",\n      \"margin_mode\": \"percent\",\n      \"option_date\": \"2026-03-14\",\n      \"transaction_date\": \"2026-03-14\",\n      \"invoice_date\": \"2026-03-18\",\n      \"cost_lines\": [\n        {\n          \"kind\": \"room_rate\",\n          \"amount\": \"1250.00\",\n          \"label\": \"Imported line\",\n          \"currency\": \"EUR\",\n          \"vat_rate\": \"20\",\n          \"tax_inclusive\": true,\n          \"quantity\": 1\n        }\n      ],\n      \"sell_lines\": [\n        {\n          \"kind\": \"package_price\",\n          \"amount\": \"1250.00\",\n          \"label\": \"Imported line\",\n          \"currency\": \"EUR\",\n          \"vat_rate\": \"20\",\n          \"tax_inclusive\": true,\n          \"quantity\": 1\n        }\n      ],\n      \"travelers\": [\n        {\n          \"first_name\": \"Ada\",\n          \"last_name\": \"Lovelace\",\n          \"nationality\": \"TR\",\n          \"national_id\": \"10000000146\",\n          \"passport_number\": \"U01234567\",\n          \"passport_country\": \"TR\",\n          \"passport_expiry\": \"2031-06-30\",\n          \"date_of_birth\": \"1988-04-21\",\n          \"gender\": \"female\",\n          \"frequent_flyer_number\": \"TK123456789\"\n        }\n      ],\n      \"rooms\": [\n        {\n          \"name\": \"Deluxe Sea View\",\n          \"room_type\": \"double\",\n          \"capacity\": 2,\n          \"occupancy\": 2,\n          \"nightly_rate\": \"180.00\",\n          \"single_supplement_amount\": \"60.00\",\n          \"single_supplement_currency\": \"EUR\"\n        }\n      ]\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200 OK\", () => pm.response.to.have.status(200));",
                  "pm.test(\"geçerli / valid\", () =>",
                  "  pm.expect(pm.response.json().import.stats.invalid).to.eql(0));"
                ]
              }
            }
          ]
        },
        {
          "name": "Hotel stays · aktar (import)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/hotel_stays",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "hotel_stays"
              ]
            },
            "description": "Aynı `external_id` ile ikinci kez gönderirseniz satır **atlanır**\n(`skipped`) — rezervasyonlar bir kez oluşturulur.\n\nSending the same `external_id` again **skips** the row — bookings are\ncreate-once.\n\nYanıttaki `results[].record.id` oluşan Lydira kaydının kimliğidir.\n`import.id` otomatik olarak `{{import_id}}` değişkenine yazılır.\n\n`results[].record.id` is the Lydira record; `import.id` is stored into\nthe `{{import_id}}` variable automatically.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source_system\": \"{{source_system}}\",\n  \"rows\": [\n    {\n      \"external_id\": \"HOTEL-STAY-1001\",\n      \"check_in_on\": \"2026-03-14\",\n      \"check_out_on\": \"2026-03-18\",\n      \"currency\": \"EUR\",\n      \"guest_count\": 2,\n      \"customer_external_id\": \"CUSTOMER-1001\",\n      \"supplier_external_id\": \"SUPPLIER-1001\",\n      \"status\": \"draft\",\n      \"notes\": \"Imported from the source system.\",\n      \"rate_basis\": \"net\",\n      \"margin_mode\": \"percent\",\n      \"option_date\": \"2026-03-14\",\n      \"transaction_date\": \"2026-03-14\",\n      \"invoice_date\": \"2026-03-18\",\n      \"cost_lines\": [\n        {\n          \"kind\": \"room_rate\",\n          \"amount\": \"1250.00\",\n          \"label\": \"Imported line\",\n          \"currency\": \"EUR\",\n          \"vat_rate\": \"20\",\n          \"tax_inclusive\": true,\n          \"quantity\": 1\n        }\n      ],\n      \"sell_lines\": [\n        {\n          \"kind\": \"package_price\",\n          \"amount\": \"1250.00\",\n          \"label\": \"Imported line\",\n          \"currency\": \"EUR\",\n          \"vat_rate\": \"20\",\n          \"tax_inclusive\": true,\n          \"quantity\": 1\n        }\n      ],\n      \"travelers\": [\n        {\n          \"first_name\": \"Ada\",\n          \"last_name\": \"Lovelace\",\n          \"nationality\": \"TR\",\n          \"national_id\": \"10000000146\",\n          \"passport_number\": \"U01234567\",\n          \"passport_country\": \"TR\",\n          \"passport_expiry\": \"2031-06-30\",\n          \"date_of_birth\": \"1988-04-21\",\n          \"gender\": \"female\",\n          \"frequent_flyer_number\": \"TK123456789\"\n        }\n      ],\n      \"rooms\": [\n        {\n          \"name\": \"Deluxe Sea View\",\n          \"room_type\": \"double\",\n          \"capacity\": 2,\n          \"occupancy\": 2,\n          \"nightly_rate\": \"180.00\",\n          \"single_supplement_amount\": \"60.00\",\n          \"single_supplement_currency\": \"EUR\"\n        }\n      ]\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"201 ya da 200 / created or idempotent\", () =>",
                  "  pm.expect(pm.response.code).to.be.oneOf([200, 201]));",
                  "pm.collectionVariables.set(\"import_id\", pm.response.json().import.id);",
                  "pm.test(\"hiç hata yok / no errors\", () => {",
                  "  const s = pm.response.json().import.stats;",
                  "  pm.expect(s.invalid + s.failed).to.eql(0);",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "Transfers · deneme (dry-run)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/transfers/validate",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "transfers",
                "validate"
              ]
            },
            "description": "Hiçbir şey yazmaz. Gerçek aktarımla **birebir aynı** yolu çalıştırır\n(rezervasyon gerçekten kurulur, sonra geri alınır), bu yüzden burada yeşil\nolan aktarımda patlamaz.\n\nWrites nothing. Runs the **identical** path the real import runs\n(a booking really is built, then thrown away), so green here cannot explode\non commit.\n\n**Zorunlu / Required:** `external_id`, `pickup_at`, `pickup_location`, `dropoff_location`\n\n**Bağlantılar / References:** `customer_external_id` → customers (skip) · `supplier_external_id` → suppliers (skip)",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source_system\": \"{{source_system}}\",\n  \"rows\": [\n    {\n      \"external_id\": \"TRANSFER-1001\",\n      \"pickup_at\": \"2026-03-14T09:30:00+03:00\",\n      \"pickup_location\": \"IST Airport\",\n      \"dropoff_location\": \"Beyoğlu, İstanbul\",\n      \"currency\": \"EUR\",\n      \"pax_count\": 2,\n      \"customer_external_id\": \"CUSTOMER-1001\",\n      \"supplier_external_id\": \"SUPPLIER-1001\",\n      \"status\": \"booked\",\n      \"notes\": \"Imported from the source system.\",\n      \"rate_basis\": \"net\",\n      \"margin_mode\": \"percent\",\n      \"transaction_date\": \"2026-03-14\",\n      \"invoice_date\": \"2026-03-18\",\n      \"cost_lines\": [\n        {\n          \"kind\": \"vehicle_fare\",\n          \"amount\": \"1250.00\",\n          \"label\": \"Imported line\",\n          \"currency\": \"EUR\",\n          \"vat_rate\": \"20\",\n          \"tax_inclusive\": true,\n          \"quantity\": 1\n        }\n      ],\n      \"sell_lines\": [\n        {\n          \"kind\": \"package_price\",\n          \"amount\": \"1250.00\",\n          \"label\": \"Imported line\",\n          \"currency\": \"EUR\",\n          \"vat_rate\": \"20\",\n          \"tax_inclusive\": true,\n          \"quantity\": 1\n        }\n      ],\n      \"travelers\": [\n        {\n          \"first_name\": \"Ada\",\n          \"last_name\": \"Lovelace\",\n          \"nationality\": \"TR\",\n          \"national_id\": \"10000000146\",\n          \"passport_number\": \"U01234567\",\n          \"passport_country\": \"TR\",\n          \"passport_expiry\": \"2031-06-30\",\n          \"date_of_birth\": \"1988-04-21\",\n          \"gender\": \"female\",\n          \"frequent_flyer_number\": \"TK123456789\"\n        }\n      ],\n      \"duration_minutes\": 2,\n      \"airline_code\": \"TK\",\n      \"flight_number\": \"1985\",\n      \"flight_date\": \"2026-03-14\"\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200 OK\", () => pm.response.to.have.status(200));",
                  "pm.test(\"geçerli / valid\", () =>",
                  "  pm.expect(pm.response.json().import.stats.invalid).to.eql(0));"
                ]
              }
            }
          ]
        },
        {
          "name": "Transfers · aktar (import)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/transfers",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "transfers"
              ]
            },
            "description": "Aynı `external_id` ile ikinci kez gönderirseniz satır **atlanır**\n(`skipped`) — rezervasyonlar bir kez oluşturulur.\n\nSending the same `external_id` again **skips** the row — bookings are\ncreate-once.\n\nYanıttaki `results[].record.id` oluşan Lydira kaydının kimliğidir.\n`import.id` otomatik olarak `{{import_id}}` değişkenine yazılır.\n\n`results[].record.id` is the Lydira record; `import.id` is stored into\nthe `{{import_id}}` variable automatically.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source_system\": \"{{source_system}}\",\n  \"rows\": [\n    {\n      \"external_id\": \"TRANSFER-1001\",\n      \"pickup_at\": \"2026-03-14T09:30:00+03:00\",\n      \"pickup_location\": \"IST Airport\",\n      \"dropoff_location\": \"Beyoğlu, İstanbul\",\n      \"currency\": \"EUR\",\n      \"pax_count\": 2,\n      \"customer_external_id\": \"CUSTOMER-1001\",\n      \"supplier_external_id\": \"SUPPLIER-1001\",\n      \"status\": \"booked\",\n      \"notes\": \"Imported from the source system.\",\n      \"rate_basis\": \"net\",\n      \"margin_mode\": \"percent\",\n      \"transaction_date\": \"2026-03-14\",\n      \"invoice_date\": \"2026-03-18\",\n      \"cost_lines\": [\n        {\n          \"kind\": \"vehicle_fare\",\n          \"amount\": \"1250.00\",\n          \"label\": \"Imported line\",\n          \"currency\": \"EUR\",\n          \"vat_rate\": \"20\",\n          \"tax_inclusive\": true,\n          \"quantity\": 1\n        }\n      ],\n      \"sell_lines\": [\n        {\n          \"kind\": \"package_price\",\n          \"amount\": \"1250.00\",\n          \"label\": \"Imported line\",\n          \"currency\": \"EUR\",\n          \"vat_rate\": \"20\",\n          \"tax_inclusive\": true,\n          \"quantity\": 1\n        }\n      ],\n      \"travelers\": [\n        {\n          \"first_name\": \"Ada\",\n          \"last_name\": \"Lovelace\",\n          \"nationality\": \"TR\",\n          \"national_id\": \"10000000146\",\n          \"passport_number\": \"U01234567\",\n          \"passport_country\": \"TR\",\n          \"passport_expiry\": \"2031-06-30\",\n          \"date_of_birth\": \"1988-04-21\",\n          \"gender\": \"female\",\n          \"frequent_flyer_number\": \"TK123456789\"\n        }\n      ],\n      \"duration_minutes\": 2,\n      \"airline_code\": \"TK\",\n      \"flight_number\": \"1985\",\n      \"flight_date\": \"2026-03-14\"\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"201 ya da 200 / created or idempotent\", () =>",
                  "  pm.expect(pm.response.code).to.be.oneOf([200, 201]));",
                  "pm.collectionVariables.set(\"import_id\", pm.response.json().import.id);",
                  "pm.test(\"hiç hata yok / no errors\", () => {",
                  "  const s = pm.response.json().import.stats;",
                  "  pm.expect(s.invalid + s.failed).to.eql(0);",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "Cruise bookings · deneme (dry-run)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/cruises/validate",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "cruises",
                "validate"
              ]
            },
            "description": "Hiçbir şey yazmaz. Gerçek aktarımla **birebir aynı** yolu çalıştırır\n(rezervasyon gerçekten kurulur, sonra geri alınır), bu yüzden burada yeşil\nolan aktarımda patlamaz.\n\nWrites nothing. Runs the **identical** path the real import runs\n(a booking really is built, then thrown away), so green here cannot explode\non commit.\n\n**Zorunlu / Required:** `external_id`\n\n**Bağlantılar / References:** `customer_external_id` → customers (skip) · `supplier_external_id` → suppliers (skip)",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source_system\": \"{{source_system}}\",\n  \"rows\": [\n    {\n      \"external_id\": \"CRUISE-1001\",\n      \"ship_name\": \"MSC Fantasia\",\n      \"embark_on\": \"2026-03-14\",\n      \"disembark_on\": \"2026-03-18\",\n      \"cabin_count\": 2,\n      \"guest_count\": 2,\n      \"currency\": \"EUR\",\n      \"customer_external_id\": \"CUSTOMER-1001\",\n      \"supplier_external_id\": \"SUPPLIER-1001\",\n      \"status\": \"draft\",\n      \"notes\": \"Imported from the source system.\",\n      \"rate_basis\": \"net\",\n      \"margin_mode\": \"percent\",\n      \"option_date\": \"2026-03-14\",\n      \"transaction_date\": \"2026-03-14\",\n      \"invoice_date\": \"2026-03-18\",\n      \"cost_lines\": [\n        {\n          \"kind\": \"cabin_fare\",\n          \"amount\": \"1250.00\",\n          \"label\": \"Imported line\",\n          \"currency\": \"EUR\",\n          \"vat_rate\": \"20\",\n          \"tax_inclusive\": true,\n          \"quantity\": 1\n        }\n      ],\n      \"sell_lines\": [\n        {\n          \"kind\": \"package_price\",\n          \"amount\": \"1250.00\",\n          \"label\": \"Imported line\",\n          \"currency\": \"EUR\",\n          \"vat_rate\": \"20\",\n          \"tax_inclusive\": true,\n          \"quantity\": 1\n        }\n      ],\n      \"travelers\": [\n        {\n          \"first_name\": \"Ada\",\n          \"last_name\": \"Lovelace\",\n          \"nationality\": \"TR\",\n          \"national_id\": \"10000000146\",\n          \"passport_number\": \"U01234567\",\n          \"passport_country\": \"TR\",\n          \"passport_expiry\": \"2031-06-30\",\n          \"date_of_birth\": \"1988-04-21\",\n          \"gender\": \"female\",\n          \"frequent_flyer_number\": \"TK123456789\"\n        }\n      ],\n      \"cabin_category\": \"balcony\"\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200 OK\", () => pm.response.to.have.status(200));",
                  "pm.test(\"geçerli / valid\", () =>",
                  "  pm.expect(pm.response.json().import.stats.invalid).to.eql(0));"
                ]
              }
            }
          ]
        },
        {
          "name": "Cruise bookings · aktar (import)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/cruises",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "cruises"
              ]
            },
            "description": "Aynı `external_id` ile ikinci kez gönderirseniz satır **atlanır**\n(`skipped`) — rezervasyonlar bir kez oluşturulur.\n\nSending the same `external_id` again **skips** the row — bookings are\ncreate-once.\n\nYanıttaki `results[].record.id` oluşan Lydira kaydının kimliğidir.\n`import.id` otomatik olarak `{{import_id}}` değişkenine yazılır.\n\n`results[].record.id` is the Lydira record; `import.id` is stored into\nthe `{{import_id}}` variable automatically.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source_system\": \"{{source_system}}\",\n  \"rows\": [\n    {\n      \"external_id\": \"CRUISE-1001\",\n      \"ship_name\": \"MSC Fantasia\",\n      \"embark_on\": \"2026-03-14\",\n      \"disembark_on\": \"2026-03-18\",\n      \"cabin_count\": 2,\n      \"guest_count\": 2,\n      \"currency\": \"EUR\",\n      \"customer_external_id\": \"CUSTOMER-1001\",\n      \"supplier_external_id\": \"SUPPLIER-1001\",\n      \"status\": \"draft\",\n      \"notes\": \"Imported from the source system.\",\n      \"rate_basis\": \"net\",\n      \"margin_mode\": \"percent\",\n      \"option_date\": \"2026-03-14\",\n      \"transaction_date\": \"2026-03-14\",\n      \"invoice_date\": \"2026-03-18\",\n      \"cost_lines\": [\n        {\n          \"kind\": \"cabin_fare\",\n          \"amount\": \"1250.00\",\n          \"label\": \"Imported line\",\n          \"currency\": \"EUR\",\n          \"vat_rate\": \"20\",\n          \"tax_inclusive\": true,\n          \"quantity\": 1\n        }\n      ],\n      \"sell_lines\": [\n        {\n          \"kind\": \"package_price\",\n          \"amount\": \"1250.00\",\n          \"label\": \"Imported line\",\n          \"currency\": \"EUR\",\n          \"vat_rate\": \"20\",\n          \"tax_inclusive\": true,\n          \"quantity\": 1\n        }\n      ],\n      \"travelers\": [\n        {\n          \"first_name\": \"Ada\",\n          \"last_name\": \"Lovelace\",\n          \"nationality\": \"TR\",\n          \"national_id\": \"10000000146\",\n          \"passport_number\": \"U01234567\",\n          \"passport_country\": \"TR\",\n          \"passport_expiry\": \"2031-06-30\",\n          \"date_of_birth\": \"1988-04-21\",\n          \"gender\": \"female\",\n          \"frequent_flyer_number\": \"TK123456789\"\n        }\n      ],\n      \"cabin_category\": \"balcony\"\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"201 ya da 200 / created or idempotent\", () =>",
                  "  pm.expect(pm.response.code).to.be.oneOf([200, 201]));",
                  "pm.collectionVariables.set(\"import_id\", pm.response.json().import.id);",
                  "pm.test(\"hiç hata yok / no errors\", () => {",
                  "  const s = pm.response.json().import.stats;",
                  "  pm.expect(s.invalid + s.failed).to.eql(0);",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "Car rentals · deneme (dry-run)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/car_rentals/validate",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "car_rentals",
                "validate"
              ]
            },
            "description": "Hiçbir şey yazmaz. Gerçek aktarımla **birebir aynı** yolu çalıştırır\n(rezervasyon gerçekten kurulur, sonra geri alınır), bu yüzden burada yeşil\nolan aktarımda patlamaz.\n\nWrites nothing. Runs the **identical** path the real import runs\n(a booking really is built, then thrown away), so green here cannot explode\non commit.\n\n**Zorunlu / Required:** `external_id`\n\n**Bağlantılar / References:** `customer_external_id` → customers (skip) · `supplier_external_id` → suppliers (skip)",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source_system\": \"{{source_system}}\",\n  \"rows\": [\n    {\n      \"external_id\": \"CAR-RENTAL-1001\",\n      \"vehicle_class\": \"compact\",\n      \"pickup_location\": \"IST Airport\",\n      \"dropoff_location\": \"Beyoğlu, İstanbul\",\n      \"pickup_at\": \"2026-03-14T09:30:00+03:00\",\n      \"return_at\": \"2026-03-14T12:45:00+03:00\",\n      \"pax_count\": 2,\n      \"currency\": \"EUR\",\n      \"customer_external_id\": \"CUSTOMER-1001\",\n      \"supplier_external_id\": \"SUPPLIER-1001\",\n      \"status\": \"draft\",\n      \"notes\": \"Imported from the source system.\",\n      \"rate_basis\": \"net\",\n      \"margin_mode\": \"percent\",\n      \"option_date\": \"2026-03-14\",\n      \"transaction_date\": \"2026-03-14\",\n      \"invoice_date\": \"2026-03-18\",\n      \"cost_lines\": [\n        {\n          \"kind\": \"daily_rate\",\n          \"amount\": \"1250.00\",\n          \"label\": \"Imported line\",\n          \"currency\": \"EUR\",\n          \"vat_rate\": \"20\",\n          \"tax_inclusive\": true,\n          \"quantity\": 1\n        }\n      ],\n      \"sell_lines\": [\n        {\n          \"kind\": \"package_price\",\n          \"amount\": \"1250.00\",\n          \"label\": \"Imported line\",\n          \"currency\": \"EUR\",\n          \"vat_rate\": \"20\",\n          \"tax_inclusive\": true,\n          \"quantity\": 1\n        }\n      ],\n      \"travelers\": [\n        {\n          \"first_name\": \"Ada\",\n          \"last_name\": \"Lovelace\",\n          \"nationality\": \"TR\",\n          \"national_id\": \"10000000146\",\n          \"passport_number\": \"U01234567\",\n          \"passport_country\": \"TR\",\n          \"passport_expiry\": \"2031-06-30\",\n          \"date_of_birth\": \"1988-04-21\",\n          \"gender\": \"female\",\n          \"frequent_flyer_number\": \"TK123456789\"\n        }\n      ]\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200 OK\", () => pm.response.to.have.status(200));",
                  "pm.test(\"geçerli / valid\", () =>",
                  "  pm.expect(pm.response.json().import.stats.invalid).to.eql(0));"
                ]
              }
            }
          ]
        },
        {
          "name": "Car rentals · aktar (import)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/car_rentals",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "car_rentals"
              ]
            },
            "description": "Aynı `external_id` ile ikinci kez gönderirseniz satır **atlanır**\n(`skipped`) — rezervasyonlar bir kez oluşturulur.\n\nSending the same `external_id` again **skips** the row — bookings are\ncreate-once.\n\nYanıttaki `results[].record.id` oluşan Lydira kaydının kimliğidir.\n`import.id` otomatik olarak `{{import_id}}` değişkenine yazılır.\n\n`results[].record.id` is the Lydira record; `import.id` is stored into\nthe `{{import_id}}` variable automatically.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source_system\": \"{{source_system}}\",\n  \"rows\": [\n    {\n      \"external_id\": \"CAR-RENTAL-1001\",\n      \"vehicle_class\": \"compact\",\n      \"pickup_location\": \"IST Airport\",\n      \"dropoff_location\": \"Beyoğlu, İstanbul\",\n      \"pickup_at\": \"2026-03-14T09:30:00+03:00\",\n      \"return_at\": \"2026-03-14T12:45:00+03:00\",\n      \"pax_count\": 2,\n      \"currency\": \"EUR\",\n      \"customer_external_id\": \"CUSTOMER-1001\",\n      \"supplier_external_id\": \"SUPPLIER-1001\",\n      \"status\": \"draft\",\n      \"notes\": \"Imported from the source system.\",\n      \"rate_basis\": \"net\",\n      \"margin_mode\": \"percent\",\n      \"option_date\": \"2026-03-14\",\n      \"transaction_date\": \"2026-03-14\",\n      \"invoice_date\": \"2026-03-18\",\n      \"cost_lines\": [\n        {\n          \"kind\": \"daily_rate\",\n          \"amount\": \"1250.00\",\n          \"label\": \"Imported line\",\n          \"currency\": \"EUR\",\n          \"vat_rate\": \"20\",\n          \"tax_inclusive\": true,\n          \"quantity\": 1\n        }\n      ],\n      \"sell_lines\": [\n        {\n          \"kind\": \"package_price\",\n          \"amount\": \"1250.00\",\n          \"label\": \"Imported line\",\n          \"currency\": \"EUR\",\n          \"vat_rate\": \"20\",\n          \"tax_inclusive\": true,\n          \"quantity\": 1\n        }\n      ],\n      \"travelers\": [\n        {\n          \"first_name\": \"Ada\",\n          \"last_name\": \"Lovelace\",\n          \"nationality\": \"TR\",\n          \"national_id\": \"10000000146\",\n          \"passport_number\": \"U01234567\",\n          \"passport_country\": \"TR\",\n          \"passport_expiry\": \"2031-06-30\",\n          \"date_of_birth\": \"1988-04-21\",\n          \"gender\": \"female\",\n          \"frequent_flyer_number\": \"TK123456789\"\n        }\n      ]\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"201 ya da 200 / created or idempotent\", () =>",
                  "  pm.expect(pm.response.code).to.be.oneOf([200, 201]));",
                  "pm.collectionVariables.set(\"import_id\", pm.response.json().import.id);",
                  "pm.test(\"hiç hata yok / no errors\", () => {",
                  "  const s = pm.response.json().import.stats;",
                  "  pm.expect(s.invalid + s.failed).to.eql(0);",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "Tour bookings · deneme (dry-run)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/tour_bookings/validate",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "tour_bookings",
                "validate"
              ]
            },
            "description": "Hiçbir şey yazmaz. Gerçek aktarımla **birebir aynı** yolu çalıştırır\n(rezervasyon gerçekten kurulur, sonra geri alınır), bu yüzden burada yeşil\nolan aktarımda patlamaz.\n\nWrites nothing. Runs the **identical** path the real import runs\n(a booking really is built, then thrown away), so green here cannot explode\non commit.\n\n**Zorunlu / Required:** `external_id`, `name`, `party_size`, `departure_external_id`\n\n**Bağlantılar / References:** `customer_external_id` → customers (skip) · `departure_external_id` → tour_departures (error)",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source_system\": \"{{source_system}}\",\n  \"rows\": [\n    {\n      \"external_id\": \"TOUR-BOOKING-1001\",\n      \"name\": \"Ada Lovelace\",\n      \"party_size\": 2,\n      \"currency\": \"EUR\",\n      \"phone\": \"+905551112233\",\n      \"status\": \"pending\",\n      \"notes\": \"Imported from the source system.\",\n      \"transaction_date\": \"2026-03-14\",\n      \"invoice_date\": \"2026-03-18\",\n      \"cost_lines\": [\n        {\n          \"kind\": \"ticket_price\",\n          \"amount\": \"1250.00\",\n          \"label\": \"Imported line\",\n          \"currency\": \"EUR\",\n          \"vat_rate\": \"20\",\n          \"tax_inclusive\": true,\n          \"quantity\": 1\n        }\n      ],\n      \"sell_lines\": [\n        {\n          \"kind\": \"package_price\",\n          \"amount\": \"1250.00\",\n          \"label\": \"Imported line\",\n          \"currency\": \"EUR\",\n          \"vat_rate\": \"20\",\n          \"tax_inclusive\": true,\n          \"quantity\": 1\n        }\n      ],\n      \"customer_external_id\": \"CUSTOMER-1001\",\n      \"departure_external_id\": \"TOUR-DEPARTURE-1001\"\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200 OK\", () => pm.response.to.have.status(200));",
                  "pm.test(\"geçerli / valid\", () =>",
                  "  pm.expect(pm.response.json().import.stats.invalid).to.eql(0));"
                ]
              }
            }
          ]
        },
        {
          "name": "Tour bookings · aktar (import)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/tour_bookings",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "tour_bookings"
              ]
            },
            "description": "Aynı `external_id` ile ikinci kez gönderirseniz satır **atlanır**\n(`skipped`) — rezervasyonlar bir kez oluşturulur.\n\nSending the same `external_id` again **skips** the row — bookings are\ncreate-once.\n\nYanıttaki `results[].record.id` oluşan Lydira kaydının kimliğidir.\n`import.id` otomatik olarak `{{import_id}}` değişkenine yazılır.\n\n`results[].record.id` is the Lydira record; `import.id` is stored into\nthe `{{import_id}}` variable automatically.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source_system\": \"{{source_system}}\",\n  \"rows\": [\n    {\n      \"external_id\": \"TOUR-BOOKING-1001\",\n      \"name\": \"Ada Lovelace\",\n      \"party_size\": 2,\n      \"currency\": \"EUR\",\n      \"phone\": \"+905551112233\",\n      \"status\": \"pending\",\n      \"notes\": \"Imported from the source system.\",\n      \"transaction_date\": \"2026-03-14\",\n      \"invoice_date\": \"2026-03-18\",\n      \"cost_lines\": [\n        {\n          \"kind\": \"ticket_price\",\n          \"amount\": \"1250.00\",\n          \"label\": \"Imported line\",\n          \"currency\": \"EUR\",\n          \"vat_rate\": \"20\",\n          \"tax_inclusive\": true,\n          \"quantity\": 1\n        }\n      ],\n      \"sell_lines\": [\n        {\n          \"kind\": \"package_price\",\n          \"amount\": \"1250.00\",\n          \"label\": \"Imported line\",\n          \"currency\": \"EUR\",\n          \"vat_rate\": \"20\",\n          \"tax_inclusive\": true,\n          \"quantity\": 1\n        }\n      ],\n      \"customer_external_id\": \"CUSTOMER-1001\",\n      \"departure_external_id\": \"TOUR-DEPARTURE-1001\"\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"201 ya da 200 / created or idempotent\", () =>",
                  "  pm.expect(pm.response.code).to.be.oneOf([200, 201]));",
                  "pm.collectionVariables.set(\"import_id\", pm.response.json().import.id);",
                  "pm.test(\"hiç hata yok / no errors\", () => {",
                  "  const s = pm.response.json().import.stats;",
                  "  pm.expect(s.invalid + s.failed).to.eql(0);",
                  "});"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "3 · Devir / Brought-forward",
      "item": [
        {
          "name": "Invoices (receivables) · deneme (dry-run)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/operator_invoices/validate",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "operator_invoices",
                "validate"
              ]
            },
            "description": "Hiçbir şey yazmaz. Gerçek aktarımla **birebir aynı** yolu çalıştırır\n(rezervasyon gerçekten kurulur, sonra geri alınır), bu yüzden burada yeşil\nolan aktarımda patlamaz.\n\nWrites nothing. Runs the **identical** path the real import runs\n(a booking really is built, then thrown away), so green here cannot explode\non commit.\n\n**Zorunlu / Required:** `external_id`, `legacy_number`, `issued_on`, `total_amount`\n\n**Bağlantılar / References:** `customer_external_id` → customers (error)",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source_system\": \"{{source_system}}\",\n  \"rows\": [\n    {\n      \"external_id\": \"OPERATOR-INVOICE-1001\",\n      \"legacy_number\": \"2025-000431\",\n      \"issued_on\": \"2026-03-14\",\n      \"due_on\": \"2026-03-18\",\n      \"total_amount\": \"1250.00\",\n      \"amount_paid\": \"1250.00\",\n      \"paid_on\": \"2026-03-14\",\n      \"currency\": \"EUR\",\n      \"bill_to_name\": \"Lovelace Seyahat A.Ş.\",\n      \"customer_external_id\": \"CUSTOMER-1001\",\n      \"notes\": \"Imported from the source system.\"\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200 OK\", () => pm.response.to.have.status(200));",
                  "pm.test(\"geçerli / valid\", () =>",
                  "  pm.expect(pm.response.json().import.stats.invalid).to.eql(0));"
                ]
              }
            }
          ]
        },
        {
          "name": "Invoices (receivables) · aktar (import)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/operator_invoices",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "operator_invoices"
              ]
            },
            "description": "Aynı `external_id` ile ikinci kez gönderirseniz kayıt **güncellenir**\n(`updated`), kopyalanmaz.\n\nSending the same `external_id` again **updates** the record, never\nduplicates it.\n\nYanıttaki `results[].record.id` oluşan Lydira kaydının kimliğidir.\n`import.id` otomatik olarak `{{import_id}}` değişkenine yazılır.\n\n`results[].record.id` is the Lydira record; `import.id` is stored into\nthe `{{import_id}}` variable automatically.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source_system\": \"{{source_system}}\",\n  \"rows\": [\n    {\n      \"external_id\": \"OPERATOR-INVOICE-1001\",\n      \"legacy_number\": \"2025-000431\",\n      \"issued_on\": \"2026-03-14\",\n      \"due_on\": \"2026-03-18\",\n      \"total_amount\": \"1250.00\",\n      \"amount_paid\": \"1250.00\",\n      \"paid_on\": \"2026-03-14\",\n      \"currency\": \"EUR\",\n      \"bill_to_name\": \"Lovelace Seyahat A.Ş.\",\n      \"customer_external_id\": \"CUSTOMER-1001\",\n      \"notes\": \"Imported from the source system.\"\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"201 ya da 200 / created or idempotent\", () =>",
                  "  pm.expect(pm.response.code).to.be.oneOf([200, 201]));",
                  "pm.collectionVariables.set(\"import_id\", pm.response.json().import.id);",
                  "pm.test(\"hiç hata yok / no errors\", () => {",
                  "  const s = pm.response.json().import.stats;",
                  "  pm.expect(s.invalid + s.failed).to.eql(0);",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "Supplier bills (payables) · deneme (dry-run)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/supplier_bills/validate",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "supplier_bills",
                "validate"
              ]
            },
            "description": "Hiçbir şey yazmaz. Gerçek aktarımla **birebir aynı** yolu çalıştırır\n(rezervasyon gerçekten kurulur, sonra geri alınır), bu yüzden burada yeşil\nolan aktarımda patlamaz.\n\nWrites nothing. Runs the **identical** path the real import runs\n(a booking really is built, then thrown away), so green here cannot explode\non commit.\n\n**Zorunlu / Required:** `external_id`, `number`, `received_at`, `total_amount`\n\n**Bağlantılar / References:** `supplier_external_id` → suppliers (error)",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source_system\": \"{{source_system}}\",\n  \"rows\": [\n    {\n      \"external_id\": \"SUPPLIER-BILL-1001\",\n      \"number\": \"TR-2025-000431\",\n      \"received_at\": \"2026-03-14\",\n      \"due_on\": \"2026-03-18\",\n      \"total_amount\": \"1250.00\",\n      \"amount_paid\": \"1250.00\",\n      \"paid_on\": \"2026-03-14\",\n      \"currency\": \"EUR\",\n      \"supplier_external_id\": \"SUPPLIER-1001\",\n      \"notes\": \"Imported from the source system.\"\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200 OK\", () => pm.response.to.have.status(200));",
                  "pm.test(\"geçerli / valid\", () =>",
                  "  pm.expect(pm.response.json().import.stats.invalid).to.eql(0));"
                ]
              }
            }
          ]
        },
        {
          "name": "Supplier bills (payables) · aktar (import)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/supplier_bills",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "supplier_bills"
              ]
            },
            "description": "Aynı `external_id` ile ikinci kez gönderirseniz kayıt **güncellenir**\n(`updated`), kopyalanmaz.\n\nSending the same `external_id` again **updates** the record, never\nduplicates it.\n\nYanıttaki `results[].record.id` oluşan Lydira kaydının kimliğidir.\n`import.id` otomatik olarak `{{import_id}}` değişkenine yazılır.\n\n`results[].record.id` is the Lydira record; `import.id` is stored into\nthe `{{import_id}}` variable automatically.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source_system\": \"{{source_system}}\",\n  \"rows\": [\n    {\n      \"external_id\": \"SUPPLIER-BILL-1001\",\n      \"number\": \"TR-2025-000431\",\n      \"received_at\": \"2026-03-14\",\n      \"due_on\": \"2026-03-18\",\n      \"total_amount\": \"1250.00\",\n      \"amount_paid\": \"1250.00\",\n      \"paid_on\": \"2026-03-14\",\n      \"currency\": \"EUR\",\n      \"supplier_external_id\": \"SUPPLIER-1001\",\n      \"notes\": \"Imported from the source system.\"\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"201 ya da 200 / created or idempotent\", () =>",
                  "  pm.expect(pm.response.code).to.be.oneOf([200, 201]));",
                  "pm.collectionVariables.set(\"import_id\", pm.response.json().import.id);",
                  "pm.test(\"hiç hata yok / no errors\", () => {",
                  "  const s = pm.response.json().import.stats;",
                  "  pm.expect(s.invalid + s.failed).to.eql(0);",
                  "});"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "4 · Listeler / Read",
      "item": [
        {
          "name": "Customers · listele (list)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/customers/records?limit=25&source_system={{source_system}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "customers",
                "records"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "25"
                },
                {
                  "key": "source_system",
                  "value": "{{source_system}}"
                }
              ]
            },
            "description": "`updated_at` **artan** sırada — bir senkronizasyon en yeniyi değil, kaldığı\nyeri ister. `updated_since=<son gördüğünüz updated_at>` ekleyip ileri\nyürüyün; sayfa için `page.next_cursor`.\n\nAjansın uygulama içinde açtığı kayıtlar da listede — mesele zaten bu.\nYalnızca sizin gönderdikleriniz için `mine=true`.\nDuruma göre süzmek için `status=…` (virgülle çoklu).\n\n`updated_at` **ascending** — a sync wants a resumable watermark, not a\nnewest-first list. Add `updated_since`, page with `page.next_cursor`.\nThe agency's own records are included on purpose; `mine=true` narrows it\nto yours, `status=…` filters (comma-separated)."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200 OK\", () => pm.response.to.have.status(200));",
                  "pm.test(\"sayfalı / paged\", () =>",
                  "  pm.expect(pm.response.json().page).to.have.property(\"next_cursor\"));",
                  "pm.test(\"eskiden yeniye / oldest change first\", () => {",
                  "  const at = pm.response.json().data.map((r) => r.updated_at);",
                  "  pm.expect(at).to.eql(at.slice().sort());",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "Suppliers · listele (list)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/suppliers/records?limit=25&source_system={{source_system}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "suppliers",
                "records"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "25"
                },
                {
                  "key": "source_system",
                  "value": "{{source_system}}"
                }
              ]
            },
            "description": "`updated_at` **artan** sırada — bir senkronizasyon en yeniyi değil, kaldığı\nyeri ister. `updated_since=<son gördüğünüz updated_at>` ekleyip ileri\nyürüyün; sayfa için `page.next_cursor`.\n\nAjansın uygulama içinde açtığı kayıtlar da listede — mesele zaten bu.\nYalnızca sizin gönderdikleriniz için `mine=true`.\nDuruma göre süzmek için `status=…` (virgülle çoklu).\n\n`updated_at` **ascending** — a sync wants a resumable watermark, not a\nnewest-first list. Add `updated_since`, page with `page.next_cursor`.\nThe agency's own records are included on purpose; `mine=true` narrows it\nto yours, `status=…` filters (comma-separated)."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200 OK\", () => pm.response.to.have.status(200));",
                  "pm.test(\"sayfalı / paged\", () =>",
                  "  pm.expect(pm.response.json().page).to.have.property(\"next_cursor\"));",
                  "pm.test(\"eskiden yeniye / oldest change first\", () => {",
                  "  const at = pm.response.json().data.map((r) => r.updated_at);",
                  "  pm.expect(at).to.eql(at.slice().sort());",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "Leads · listele (list)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/leads/records?limit=25&source_system={{source_system}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "leads",
                "records"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "25"
                },
                {
                  "key": "source_system",
                  "value": "{{source_system}}"
                }
              ]
            },
            "description": "`updated_at` **artan** sırada — bir senkronizasyon en yeniyi değil, kaldığı\nyeri ister. `updated_since=<son gördüğünüz updated_at>` ekleyip ileri\nyürüyün; sayfa için `page.next_cursor`.\n\nAjansın uygulama içinde açtığı kayıtlar da listede — mesele zaten bu.\nYalnızca sizin gönderdikleriniz için `mine=true`.\nDuruma göre süzmek için `status=…` (virgülle çoklu).\n\n`updated_at` **ascending** — a sync wants a resumable watermark, not a\nnewest-first list. Add `updated_since`, page with `page.next_cursor`.\nThe agency's own records are included on purpose; `mine=true` narrows it\nto yours, `status=…` filters (comma-separated)."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200 OK\", () => pm.response.to.have.status(200));",
                  "pm.test(\"sayfalı / paged\", () =>",
                  "  pm.expect(pm.response.json().page).to.have.property(\"next_cursor\"));",
                  "pm.test(\"eskiden yeniye / oldest change first\", () => {",
                  "  const at = pm.response.json().data.map((r) => r.updated_at);",
                  "  pm.expect(at).to.eql(at.slice().sort());",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "Tour departures · listele (list)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/tour_departures/records?limit=25&source_system={{source_system}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "tour_departures",
                "records"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "25"
                },
                {
                  "key": "source_system",
                  "value": "{{source_system}}"
                }
              ]
            },
            "description": "`updated_at` **artan** sırada — bir senkronizasyon en yeniyi değil, kaldığı\nyeri ister. `updated_since=<son gördüğünüz updated_at>` ekleyip ileri\nyürüyün; sayfa için `page.next_cursor`.\n\nAjansın uygulama içinde açtığı kayıtlar da listede — mesele zaten bu.\nYalnızca sizin gönderdikleriniz için `mine=true`.\nDuruma göre süzmek için `status=…` (virgülle çoklu).\n\n`updated_at` **ascending** — a sync wants a resumable watermark, not a\nnewest-first list. Add `updated_since`, page with `page.next_cursor`.\nThe agency's own records are included on purpose; `mine=true` narrows it\nto yours, `status=…` filters (comma-separated)."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200 OK\", () => pm.response.to.have.status(200));",
                  "pm.test(\"sayfalı / paged\", () =>",
                  "  pm.expect(pm.response.json().page).to.have.property(\"next_cursor\"));",
                  "pm.test(\"eskiden yeniye / oldest change first\", () => {",
                  "  const at = pm.response.json().data.map((r) => r.updated_at);",
                  "  pm.expect(at).to.eql(at.slice().sort());",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "Car rentals · listele (list)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/car_rentals/records?limit=25&source_system={{source_system}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "car_rentals",
                "records"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "25"
                },
                {
                  "key": "source_system",
                  "value": "{{source_system}}"
                }
              ]
            },
            "description": "`updated_at` **artan** sırada — bir senkronizasyon en yeniyi değil, kaldığı\nyeri ister. `updated_since=<son gördüğünüz updated_at>` ekleyip ileri\nyürüyün; sayfa için `page.next_cursor`.\n\nAjansın uygulama içinde açtığı kayıtlar da listede — mesele zaten bu.\nYalnızca sizin gönderdikleriniz için `mine=true`.\nDuruma göre süzmek için `status=…` (virgülle çoklu).\n\n`updated_at` **ascending** — a sync wants a resumable watermark, not a\nnewest-first list. Add `updated_since`, page with `page.next_cursor`.\nThe agency's own records are included on purpose; `mine=true` narrows it\nto yours, `status=…` filters (comma-separated)."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200 OK\", () => pm.response.to.have.status(200));",
                  "pm.test(\"sayfalı / paged\", () =>",
                  "  pm.expect(pm.response.json().page).to.have.property(\"next_cursor\"));",
                  "pm.test(\"eskiden yeniye / oldest change first\", () => {",
                  "  const at = pm.response.json().data.map((r) => r.updated_at);",
                  "  pm.expect(at).to.eql(at.slice().sort());",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "Cruise bookings · listele (list)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/cruises/records?limit=25&source_system={{source_system}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "cruises",
                "records"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "25"
                },
                {
                  "key": "source_system",
                  "value": "{{source_system}}"
                }
              ]
            },
            "description": "`updated_at` **artan** sırada — bir senkronizasyon en yeniyi değil, kaldığı\nyeri ister. `updated_since=<son gördüğünüz updated_at>` ekleyip ileri\nyürüyün; sayfa için `page.next_cursor`.\n\nAjansın uygulama içinde açtığı kayıtlar da listede — mesele zaten bu.\nYalnızca sizin gönderdikleriniz için `mine=true`.\nDuruma göre süzmek için `status=…` (virgülle çoklu).\n\n`updated_at` **ascending** — a sync wants a resumable watermark, not a\nnewest-first list. Add `updated_since`, page with `page.next_cursor`.\nThe agency's own records are included on purpose; `mine=true` narrows it\nto yours, `status=…` filters (comma-separated)."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200 OK\", () => pm.response.to.have.status(200));",
                  "pm.test(\"sayfalı / paged\", () =>",
                  "  pm.expect(pm.response.json().page).to.have.property(\"next_cursor\"));",
                  "pm.test(\"eskiden yeniye / oldest change first\", () => {",
                  "  const at = pm.response.json().data.map((r) => r.updated_at);",
                  "  pm.expect(at).to.eql(at.slice().sort());",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "Hotel stays · listele (list)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/hotel_stays/records?limit=25&source_system={{source_system}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "hotel_stays",
                "records"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "25"
                },
                {
                  "key": "source_system",
                  "value": "{{source_system}}"
                }
              ]
            },
            "description": "`updated_at` **artan** sırada — bir senkronizasyon en yeniyi değil, kaldığı\nyeri ister. `updated_since=<son gördüğünüz updated_at>` ekleyip ileri\nyürüyün; sayfa için `page.next_cursor`.\n\nAjansın uygulama içinde açtığı kayıtlar da listede — mesele zaten bu.\nYalnızca sizin gönderdikleriniz için `mine=true`.\nDuruma göre süzmek için `status=…` (virgülle çoklu).\n\n`updated_at` **ascending** — a sync wants a resumable watermark, not a\nnewest-first list. Add `updated_since`, page with `page.next_cursor`.\nThe agency's own records are included on purpose; `mine=true` narrows it\nto yours, `status=…` filters (comma-separated)."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200 OK\", () => pm.response.to.have.status(200));",
                  "pm.test(\"sayfalı / paged\", () =>",
                  "  pm.expect(pm.response.json().page).to.have.property(\"next_cursor\"));",
                  "pm.test(\"eskiden yeniye / oldest change first\", () => {",
                  "  const at = pm.response.json().data.map((r) => r.updated_at);",
                  "  pm.expect(at).to.eql(at.slice().sort());",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "Tickets · listele (list)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/tickets/records?limit=25&source_system={{source_system}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "tickets",
                "records"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "25"
                },
                {
                  "key": "source_system",
                  "value": "{{source_system}}"
                }
              ]
            },
            "description": "`updated_at` **artan** sırada — bir senkronizasyon en yeniyi değil, kaldığı\nyeri ister. `updated_since=<son gördüğünüz updated_at>` ekleyip ileri\nyürüyün; sayfa için `page.next_cursor`.\n\nAjansın uygulama içinde açtığı kayıtlar da listede — mesele zaten bu.\nYalnızca sizin gönderdikleriniz için `mine=true`.\nDuruma göre süzmek için `status=…` (virgülle çoklu).\n\n`updated_at` **ascending** — a sync wants a resumable watermark, not a\nnewest-first list. Add `updated_since`, page with `page.next_cursor`.\nThe agency's own records are included on purpose; `mine=true` narrows it\nto yours, `status=…` filters (comma-separated)."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200 OK\", () => pm.response.to.have.status(200));",
                  "pm.test(\"sayfalı / paged\", () =>",
                  "  pm.expect(pm.response.json().page).to.have.property(\"next_cursor\"));",
                  "pm.test(\"eskiden yeniye / oldest change first\", () => {",
                  "  const at = pm.response.json().data.map((r) => r.updated_at);",
                  "  pm.expect(at).to.eql(at.slice().sort());",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "Tour bookings · listele (list)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/tour_bookings/records?limit=25&source_system={{source_system}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "tour_bookings",
                "records"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "25"
                },
                {
                  "key": "source_system",
                  "value": "{{source_system}}"
                }
              ]
            },
            "description": "`updated_at` **artan** sırada — bir senkronizasyon en yeniyi değil, kaldığı\nyeri ister. `updated_since=<son gördüğünüz updated_at>` ekleyip ileri\nyürüyün; sayfa için `page.next_cursor`.\n\nAjansın uygulama içinde açtığı kayıtlar da listede — mesele zaten bu.\nYalnızca sizin gönderdikleriniz için `mine=true`.\nDuruma göre süzmek için `status=…` (virgülle çoklu).\n\n`updated_at` **ascending** — a sync wants a resumable watermark, not a\nnewest-first list. Add `updated_since`, page with `page.next_cursor`.\nThe agency's own records are included on purpose; `mine=true` narrows it\nto yours, `status=…` filters (comma-separated)."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200 OK\", () => pm.response.to.have.status(200));",
                  "pm.test(\"sayfalı / paged\", () =>",
                  "  pm.expect(pm.response.json().page).to.have.property(\"next_cursor\"));",
                  "pm.test(\"eskiden yeniye / oldest change first\", () => {",
                  "  const at = pm.response.json().data.map((r) => r.updated_at);",
                  "  pm.expect(at).to.eql(at.slice().sort());",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "Transfers · listele (list)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/transfers/records?limit=25&source_system={{source_system}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "transfers",
                "records"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "25"
                },
                {
                  "key": "source_system",
                  "value": "{{source_system}}"
                }
              ]
            },
            "description": "`updated_at` **artan** sırada — bir senkronizasyon en yeniyi değil, kaldığı\nyeri ister. `updated_since=<son gördüğünüz updated_at>` ekleyip ileri\nyürüyün; sayfa için `page.next_cursor`.\n\nAjansın uygulama içinde açtığı kayıtlar da listede — mesele zaten bu.\nYalnızca sizin gönderdikleriniz için `mine=true`.\nDuruma göre süzmek için `status=…` (virgülle çoklu).\n\n`updated_at` **ascending** — a sync wants a resumable watermark, not a\nnewest-first list. Add `updated_since`, page with `page.next_cursor`.\nThe agency's own records are included on purpose; `mine=true` narrows it\nto yours, `status=…` filters (comma-separated)."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200 OK\", () => pm.response.to.have.status(200));",
                  "pm.test(\"sayfalı / paged\", () =>",
                  "  pm.expect(pm.response.json().page).to.have.property(\"next_cursor\"));",
                  "pm.test(\"eskiden yeniye / oldest change first\", () => {",
                  "  const at = pm.response.json().data.map((r) => r.updated_at);",
                  "  pm.expect(at).to.eql(at.slice().sort());",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "Invoices (receivables) · listele (list)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/operator_invoices/records?limit=25&source_system={{source_system}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "operator_invoices",
                "records"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "25"
                },
                {
                  "key": "source_system",
                  "value": "{{source_system}}"
                }
              ]
            },
            "description": "`updated_at` **artan** sırada — bir senkronizasyon en yeniyi değil, kaldığı\nyeri ister. `updated_since=<son gördüğünüz updated_at>` ekleyip ileri\nyürüyün; sayfa için `page.next_cursor`.\n\nAjansın uygulama içinde açtığı kayıtlar da listede — mesele zaten bu.\nYalnızca sizin gönderdikleriniz için `mine=true`.\nDuruma göre süzmek için `status=…` (virgülle çoklu).\n\n`updated_at` **ascending** — a sync wants a resumable watermark, not a\nnewest-first list. Add `updated_since`, page with `page.next_cursor`.\nThe agency's own records are included on purpose; `mine=true` narrows it\nto yours, `status=…` filters (comma-separated)."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200 OK\", () => pm.response.to.have.status(200));",
                  "pm.test(\"sayfalı / paged\", () =>",
                  "  pm.expect(pm.response.json().page).to.have.property(\"next_cursor\"));",
                  "pm.test(\"eskiden yeniye / oldest change first\", () => {",
                  "  const at = pm.response.json().data.map((r) => r.updated_at);",
                  "  pm.expect(at).to.eql(at.slice().sort());",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "Supplier bills (payables) · listele (list)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/supplier_bills/records?limit=25&source_system={{source_system}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "supplier_bills",
                "records"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "25"
                },
                {
                  "key": "source_system",
                  "value": "{{source_system}}"
                }
              ]
            },
            "description": "`updated_at` **artan** sırada — bir senkronizasyon en yeniyi değil, kaldığı\nyeri ister. `updated_since=<son gördüğünüz updated_at>` ekleyip ileri\nyürüyün; sayfa için `page.next_cursor`.\n\nAjansın uygulama içinde açtığı kayıtlar da listede — mesele zaten bu.\nYalnızca sizin gönderdikleriniz için `mine=true`.\nDuruma göre süzmek için `status=…` (virgülle çoklu).\n\n`updated_at` **ascending** — a sync wants a resumable watermark, not a\nnewest-first list. Add `updated_since`, page with `page.next_cursor`.\nThe agency's own records are included on purpose; `mine=true` narrows it\nto yours, `status=…` filters (comma-separated)."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200 OK\", () => pm.response.to.have.status(200));",
                  "pm.test(\"sayfalı / paged\", () =>",
                  "  pm.expect(pm.response.json().page).to.have.property(\"next_cursor\"));",
                  "pm.test(\"eskiden yeniye / oldest change first\", () => {",
                  "  const at = pm.response.json().data.map((r) => r.updated_at);",
                  "  pm.expect(at).to.eql(at.slice().sort());",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "Tek kaydı oku / Read one by your id",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/hotel_stays/records/HOTEL-STAY-1001?source_system={{source_system}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "hotel_stays",
                "records",
                "HOTEL-STAY-1001"
              ],
              "query": [
                {
                  "key": "source_system",
                  "value": "{{source_system}}"
                }
              ]
            },
            "description": "Kendi kimliğinizle Lydira'daki güncel durum: durum, kilit (faturalandı /\niptal edildi ⇒ değişiklikleriniz reddedilecek), tutarlar ve faturalar.\nGövde listedeki satırla ve webhook gövdesiyle **birebir aynı** — tek bir\nokuyucu üçüne de yeter.\n\nThe live state by YOUR id: status, the freeze (invoiced / cancelled ⇒ your\namendments will be refused), totals and invoices. The body is identical to\na list row and to the webhook payload — one parser covers all three."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200\", () => pm.response.to.have.status(200));",
                  "pm.test(\"kilit durumu bildirilir / lock state reported\", () =>",
                  "  pm.expect(pm.response.json().record).to.have.property(\"locked\"));"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "5 · Değişiklik & iptal / Amend & cancel",
      "item": [
        {
          "name": "Rezervasyonu güncelle / Amend a booking",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/hotel_stays",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "hotel_stays"
              ]
            },
            "description": "`on_conflict: \"update\"` olmadan aynı `external_id` **atlanır** — varsayılan\nbudur, ki bir tekrar gönderim mevcut rezervasyonu sessizce yeniden yazmasın.\nYalnızca kayıt tipinin izin verdiği alanlar uygulanır; `status` durum\nmakinesinden geçer, fiyat satırları API'den değiştirilemez.\n\nWithout `on_conflict: \"update\"` a known `external_id` is **skipped** — the\ndefault, so a replay never silently rewrites a booking. Only the entity's\nallowlisted fields apply; `status` moves through the state machine, and\npricing is not amendable over the API.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source_system\": \"{{source_system}}\",\n  \"on_conflict\": \"update\",\n  \"rows\": [\n    {\n      \"external_id\": \"HOTEL-STAY-1001\",\n      \"check_in_on\": \"2026-03-14\",\n      \"check_out_on\": \"2026-03-18\",\n      \"guest_count\": 3,\n      \"status\": \"confirmed\",\n      \"notes\": \"Misafir sayısı güncellendi.\"\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200\", () => pm.response.to.have.status(200));",
                  "pm.test(\"güncellendi / updated\", () =>",
                  "  pm.expect(pm.response.json().results[0].status).to.eql(\"updated\"));"
                ]
              }
            }
          ]
        },
        {
          "name": "Rezervasyonu iptal et / Cancel a booking",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/hotel_stays",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "hotel_stays"
              ]
            },
            "description": "`status: \"cancelled\"` düz bir alan yazımı DEĞİLDİR: müşteri faturasını ters\nçevirir ve tedarikçi fişini void eder. Zaten\niptal edilmiş bir kaydı tekrar göndermek `skipped` döner — değişiklik\nakışınızı güvenle yeniden oynatabilirsiniz.\n\n`status: \"cancelled\"` is not a field write: it reverses the customer\ninvoice and voids the supplier bill. Re-sending an already-cancelled\nrecord answers `skipped`, so a change feed can be replayed safely.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source_system\": \"{{source_system}}\",\n  \"on_conflict\": \"update\",\n  \"rows\": [\n    {\n      \"external_id\": \"HOTEL-STAY-1001\",\n      \"check_in_on\": \"2026-03-14\",\n      \"check_out_on\": \"2026-03-18\",\n      \"status\": \"cancelled\"\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200\", () => pm.response.to.have.status(200));",
                  "pm.test(\"iptal ya da zaten iptal / cancelled or already\", () =>",
                  "  pm.expect(pm.response.json().results[0].status).to.be.oneOf([\"updated\", \"skipped\"]));"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "6 · Parti takibi / Batch log",
      "item": [
        {
          "name": "Partileri listele / List batches",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/v1/imports?limit=20",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "20"
                }
              ]
            },
            "description": "Bu hesabın API aktarım geçmişi, yeniden eskiye. Her liste gibi\n`{ data, page }` döner; sonraki sayfa için `page.next_cursor`.\n\nThis account's API import history, newest first. Like every list here it\nanswers `{ data, page }`; page with `page.next_cursor`."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200 OK\", () => pm.response.to.have.status(200));",
                  "pm.test(\"sayfalı / paged\", () =>",
                  "  pm.expect(pm.response.json().page).to.have.property(\"next_cursor\"));"
                ]
              }
            }
          ]
        },
        {
          "name": "Bir parti / One batch",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/{{import_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "{{import_id}}"
              ]
            },
            "description": "`mode=async` ile gönderdiğiniz bir partinin durumunu buradan\nyoklarsınız (`status`: importing → completed | partial).\n\nPoll here for a batch you sent with `mode=async`\n(`status`: importing → completed | partial)."
          }
        },
        {
          "name": "Hatalı satırlar / Failed rows",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/{{import_id}}/rows?status=invalid,failed",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "{{import_id}}",
                "rows"
              ],
              "query": [
                {
                  "key": "status",
                  "value": "invalid,failed"
                }
              ]
            },
            "description": "Düzeltilecek satırların listesi: her satırın kaynak kimliği ve\nalan bazında hata sebebi. Satırlar `data` altında, ait oldukları\nparti ise `import` altında gelir; sayımlar `import.stats` içinde.\n\nThe fix-list: each row's source id and its per-field reason. The rows\nare `data`, the batch they belong to rides alongside as `import`, and\nthe counts are in `import.stats`."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200 OK\", () => pm.response.to.have.status(200));",
                  "pm.test(\"satırlar data altında / rows live under data\", () =>",
                  "  pm.expect(pm.response.json().data).to.be.an(\"array\"));"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "7 · Hata senaryoları / Failure modes",
      "item": [
        {
          "name": "external_id yok → 422 / Missing external_id → 422",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/customers",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "customers"
              ]
            },
            "description": "Her satır kaynak sistemin kendi kimliğini taşımak zorundadır —\ntekrar gönderim ancak böyle güvenlidir. Taşımayan satır **içeri\nalınmaz**, sessizce kopyalanmaz.\n\nEvery row must carry the source system's own id — that is what makes a\nretry safe. A row without one is **rejected**, never silently duplicated.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source_system\": \"{{source_system}}\",\n  \"rows\": [\n    {\n      \"name\": \"Kaynak kimliği olmayan müşteri\"\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"422\", () => pm.response.to.have.status(422));",
                  "pm.test(\"alan bazında sebep / per-field reason\", () =>",
                  "  pm.expect(pm.response.json().results[0].errors).to.have.property(\"external_id\"));"
                ]
              }
            }
          ]
        },
        {
          "name": "Bilinmeyen tip → 404 / Unknown entity → 404",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/wombats",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "wombats"
              ]
            },
            "description": "Katalogda olmayan bir tip. / An entity that isn't in the catalogue.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"rows\": [\n    {\n      \"external_id\": \"X-1\"\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"404\", () => pm.response.to.have.status(404));"
                ]
              }
            }
          ]
        },
        {
          "name": "Bozuk satır izole edilir / A bad row is isolated",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v1/imports/cruises/validate",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v1",
                "imports",
                "cruises",
                "validate"
              ]
            },
            "description": "Tek bozuk satır partiyi durdurmaz: diğerleri geçer, bozuk olan\nkonumuyla birlikte raporlanır (`cost_lines[0].amount`).\n\nOne bad row never aborts the batch: the rest pass, and the bad one is\nreported with its exact position (`cost_lines[0].amount`).",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source_system\": \"{{source_system}}\",\n  \"rows\": [\n    {\n      \"external_id\": \"CRUISE-OK\",\n      \"ship_name\": \"MSC Fantasia\",\n      \"embark_on\": \"2026-03-14\"\n    },\n    {\n      \"external_id\": \"CRUISE-BAD\",\n      \"ship_name\": \"MSC\",\n      \"embark_on\": \"tarih-değil\",\n      \"cost_lines\": [\n        {\n          \"kind\": \"cabin_fare\",\n          \"amount\": \"abc\"\n        }\n      ]\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200\", () => pm.response.to.have.status(200));",
                  "const r = pm.response.json().results;",
                  "pm.test(\"biri geçerli, biri değil / one valid, one not\", () => {",
                  "  pm.expect(r[0].status).to.eql(\"will_create\");",
                  "  pm.expect(r[1].status).to.eql(\"invalid\");",
                  "});"
                ]
              }
            }
          ]
        }
      ]
    }
  ]
}
