> ## Documentation Index
> Fetch the complete documentation index at: https://teardowns.aero/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Create a sales / lease / exchange

> POST a new sales / lease / exchange via the public API.

Create a new sales / lease / exchange owned by your organization.
These represent whole aircraft, engines, or APUs your team is
offering for sale, lease, or exchange.

<Note>
  The public API supports `listing_type` of `aircraft`, `engine`, or
  `apu` only. `parts` and `landing_gear` are intentionally excluded
  from the public surface today — existing rows of those types stay
  readable on GET, but cannot be created via this endpoint and sending
  either returns `422`.
</Note>

## Headers

<ParamField header="Authorization" type="string" required>
  `Bearer tdao_live_…`
</ParamField>

<ParamField header="X-Organization-Id" type="string" required>
  Your organization's UUID.
</ParamField>

<ParamField header="Content-Type" type="string" required>
  `application/json`
</ParamField>

## Body

The request body shape depends on the `listing_type` you pick. Three
fields are required on every request regardless of type, and each
type then has its own set of required and optional fields on top.

Sending a request that's missing a required field returns `422` with
a single error message naming every missing field, so you can fix
all of them in one round trip.

### Universal required fields (every listing\_type)

These three are required on every request, no matter which type you
are creating.

<ParamField body="listing_type" type="string" required>
  One of `aircraft`, `engine`, or `apu`. Sending `parts` or
  `landing_gear` returns `422`.
</ParamField>

<ParamField body="price_usd" type="number" required>
  Asking price in USD. UI label: "Price (\$) \*".
</ParamField>

<ParamField body="country" type="string" required>
  ISO country code, e.g. `IN`. UI label: "Country \*" / "Location \*".
</ParamField>

***

### `listing_type = "aircraft"`

Mirrors the UI wizard's Aircraft Details step exactly.

#### Required for aircraft

<ParamField body="aircraft_type" type="string" required>
  Human-readable name from the aircraft-types vocabulary, e.g.
  `A320-200`. Case-insensitive. Unknown values return
  `400 unknown_vocabulary` with the full allowed list in the body.
  UI label: "Aircraft Model \*".
</ParamField>

<ParamField body="quantity" type="integer" required>
  How many of this aircraft are on offer. UI label: "Quantity \*".
  UI form defaults to `1` but the API has no default — send the
  value explicitly.
</ParamField>

<ParamField body="incident_related" type="string" required>
  `Yes` or `No`. UI label: "Incident Related \*".
</ParamField>

#### Optional for aircraft

<ParamField body="manufacturer" type="string">
  Aircraft manufacturer, e.g. `Boeing`. UI label: "Manufacturer".
</ParamField>

<ParamField body="year_of_manufacture" type="integer">
  Year the aircraft was built. UI label: "Year".
</ParamField>

<ParamField body="registration" type="string">
  Aircraft tail number. UI label: "Tail Number".
</ParamField>

<ParamField body="traceability" type="string">
  Last operator / traceability history. UI label: "Traceability".
</ParamField>

<ParamField body="engines_description" type="string">
  Free-text description of the engines on the aircraft. UI label:
  "Engines".
</ParamField>

<ParamField body="apu_description" type="string">
  Free-text description of the APU on the aircraft. UI label: "APU".
</ParamField>

<ParamField body="total_hours" type="number">
  Total airframe hours. UI label: "Total Hours".
</ParamField>

<ParamField body="total_cycles" type="integer">
  Total airframe cycles. UI label: "Total Cycles".
</ParamField>

<ParamField body="description" type="string">
  Free-text description shown on the listing detail page. UI label:
  "Description".
</ParamField>

***

### `listing_type = "engine"`

Mirrors the UI wizard's Engine Details step exactly.

#### Required for engine

<ParamField body="engine_model" type="string" required>
  Human-readable name from the engine-models vocabulary, e.g.
  `CFM56-5B`. Case-insensitive. UI label: "Engine Model \*".
</ParamField>

<ParamField body="msn" type="string" required>
  Engine serial number. UI label: "ESN \*".
</ParamField>

<ParamField body="cycles_remaining" type="number" required>
  Cycles remaining (in hours). UI label: "Cycles Remaining (hours) \*".
</ParamField>

<ParamField body="available_date" type="string (date)" required>
  ISO date the engine is available. UI label: "Available Date \*".
  UI form defaults to today; the API has no default.
</ParamField>

<ParamField body="condition" type="string" required>
  One of `Serviceable`, `As Removed`, `Overhauled`, `Repaired`.
  UI label: "Condition \*".
</ParamField>

<ParamField body="quantity" type="integer" required>
  UI label: "Quantity \*".
</ParamField>

<ParamField body="listing_purpose" type="array of string" required>
  Non-empty array containing any of `sale`, `lease`, `exchange`.
  Empty array is rejected. UI label: "Sale / Lease / Exchange".
</ParamField>

#### Optional for engine

<ParamField body="manufacturer" type="string">
  Engine manufacturer. UI label: "Manufacturer". The UI auto-fills
  this from the selected engine model; the API does not.
</ParamField>

<ParamField body="description" type="string">
  Free-text description. UI label: "Description".
</ParamField>

***

### `listing_type = "apu"`

Mirrors the UI wizard's APU Details step exactly.

#### Required for apu

<ParamField body="apu_model" type="string" required>
  Human-readable name from the apu-models vocabulary, e.g.
  `APS3200`. Case-insensitive. UI label: "APU Model \*".
</ParamField>

<ParamField body="manufacturer" type="string" required>
  APU manufacturer, e.g. `Honeywell`. UI label: "Manufacturer \*".
  The UI auto-fills this from the selected APU model; the API does
  not.
</ParamField>

<ParamField body="msn" type="string" required>
  APU serial number. UI label: "SN \*".
</ParamField>

<ParamField body="available_date" type="string (date)" required>
  ISO date the APU is available. UI label: "Available Date \*".
</ParamField>

<ParamField body="condition" type="string" required>
  One of `Serviceable`, `As Removed`, `Overhauled`, `Repaired`.
  UI label: "Condition \*".
</ParamField>

<ParamField body="quantity" type="integer" required>
  UI label: "Quantity \*".
</ParamField>

#### Optional for apu

<ParamField body="listing_purpose" type="array of string">
  Array containing any of `sale`, `lease`, `exchange`. UI label:
  "Sale / Lease / Exchange".
</ParamField>

<ParamField body="description" type="string">
  Free-text description. UI label: "Description".
</ParamField>

***

<Warning>
  Strict mode is on for this endpoint. Sending an unknown body key
  returns `422` and tells you which key was wrong. Common stale names
  to avoid: `aircraft_type_id` / `engine_model_id` / `apu_model_id`
  (use the **name**, not the UUID), `location_country` (use `country`),
  `listing_type=parts` / `listing_type=landing_gear` (not supported on
  the public surface).
</Warning>

## Response

`201 Created`. The full listing in the shape every GET returns.

<RequestExample>
  ```bash aircraft theme={null}
  curl -X POST "$base_url/public/v1/sales-lease-exchange" \
    -H "Authorization: Bearer $api_key" \
    -H "X-Organization-Id: $org_id" \
    -H "Content-Type: application/json" \
    -d '{
      "listing_type": "aircraft",
      "aircraft_type": "A320-200",
      "quantity": 1,
      "incident_related": "No",
      "price_usd": 4500000,
      "country": "US",
      "manufacturer": "Airbus",
      "year_of_manufacture": 2008,
      "registration": "VT-AER1",
      "traceability": "Delta",
      "total_hours": 62000,
      "total_cycles": 31000,
      "description": "Narrowbody, full traceability"
    }'
  ```

  ```bash engine theme={null}
  curl -X POST "$base_url/public/v1/sales-lease-exchange" \
    -H "Authorization: Bearer $api_key" \
    -H "X-Organization-Id: $org_id" \
    -H "Content-Type: application/json" \
    -d '{
      "listing_type": "engine",
      "engine_model": "CFM56-5B",
      "msn": "ESN-9876",
      "cycles_remaining": 12000,
      "available_date": "2026-08-01",
      "condition": "Serviceable",
      "quantity": 1,
      "listing_purpose": ["sale", "lease"],
      "price_usd": 250000,
      "country": "IN",
      "description": "Low-cycle engine, full traceability"
    }'
  ```

  ```bash apu theme={null}
  curl -X POST "$base_url/public/v1/sales-lease-exchange" \
    -H "Authorization: Bearer $api_key" \
    -H "X-Organization-Id: $org_id" \
    -H "Content-Type: application/json" \
    -d '{
      "listing_type": "apu",
      "apu_model": "APS3200",
      "manufacturer": "Pratt & Whitney",
      "msn": "APU-3200-01",
      "available_date": "2026-07-15",
      "condition": "Serviceable",
      "quantity": 1,
      "price_usd": 95000,
      "country": "US",
      "listing_purpose": ["sale"],
      "description": "Serviceable APU, full records"
    }'
  ```

  ```python python theme={null}
  import requests

  # Aircraft listing
  resp = requests.post(
      f"{base_url}/public/v1/sales-lease-exchange",
      headers={"Authorization": f"Bearer {api_key}", "X-Organization-Id": org_id},
      json={
          "listing_type": "aircraft",
          "aircraft_type": "A320-200",
          "quantity": 1,
          "incident_related": "No",
          "price_usd": 4_500_000,
          "country": "US",
      },
  )

  # Engine listing
  resp = requests.post(
      f"{base_url}/public/v1/sales-lease-exchange",
      headers={"Authorization": f"Bearer {api_key}", "X-Organization-Id": org_id},
      json={
          "listing_type": "engine",
          "engine_model": "CFM56-5B",
          "msn": "ESN-9876",
          "cycles_remaining": 12000,
          "available_date": "2026-08-01",
          "condition": "Serviceable",
          "quantity": 1,
          "listing_purpose": ["sale", "lease"],
          "price_usd": 250_000,
          "country": "IN",
      },
  )

  # APU listing
  resp = requests.post(
      f"{base_url}/public/v1/sales-lease-exchange",
      headers={"Authorization": f"Bearer {api_key}", "X-Organization-Id": org_id},
      json={
          "listing_type": "apu",
          "apu_model": "APS3200",
          "manufacturer": "Pratt & Whitney",
          "msn": "APU-3200-01",
          "available_date": "2026-07-15",
          "condition": "Serviceable",
          "quantity": 1,
          "price_usd": 95_000,
          "country": "US",
      },
  )
  resp.raise_for_status()
  listing_id = resp.json()["id"]
  ```
</RequestExample>

<ResponseExample>
  ```jsonc 201 Created theme={null}
  {
    "id": "df1e...",
    "org_id": "72f95f4e-...",
    "listing_type": "engine",
    "engine_model_id": "...",
    "engine_model": { "name": "CFM56-5B", "manufacturer": "CFM International", ... },
    "msn": "ESN-9876",
    "condition": "Serviceable",
    "price_usd": 250000,
    "country": "IN",
    "documents": null,
    "images": null,
    "audience": null,
    "status": "active",
    "created_at": "..."
  }
  ```

  ```jsonc 400 Unknown vocabulary theme={null}
  {
    "detail": {
      "error_code": "unknown_vocabulary",
      "field": "engine_model",
      "value": "cfm-foo",
      "valid_values": ["CFM56-3", "CFM56-5B", "CFM56-7B", "LEAP-1A", ...],
      "message": "Unknown engine_model: 'cfm-foo'. See valid_values."
    }
  }
  ```

  ```jsonc 422 Missing vocab name for typed listing theme={null}
  {
    "detail": {
      "error_code": "vocab_required",
      "message": "engine_model is required for listing_type='engine'"
    }
  }
  ```

  ```jsonc 422 Missing per-type required fields theme={null}
  {
    "detail": [
      {
        "type": "value_error",
        "loc": ["body"],
        "msg": "Value error, listing_type='engine' requires the following fields: msn, cycles_remaining, available_date, condition, quantity, listing_purpose",
        "input": { /* the request body you sent */ }
      }
    ]
  }
  ```
</ResponseExample>

## Notes

* Listings go directly to `active` status — there's no draft path.
* `audience` is not set at create time. Attach it on the same call
  that uploads the first document (see the upload endpoints) or via
  PATCH later.
* Use [the upload endpoints](/api-reference/uploads/listing-documents)
  to attach documents and images.

## See also

* [List sales / lease / exchanges](/api-reference/listings/list)
* [Update a sales / lease / exchange](/api-reference/listings/update)
* [Delete a sales / lease / exchange](/api-reference/listings/delete)
* [Vocabularies](/concepts/vocabularies) for the accepted names.
* [Audience](/concepts/audience)
