> For the complete documentation index, see [llms.txt](https://docs.tradevest.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.tradevest.ai/documentation/traditional-trading-orders-with-tradevest.md).

# Traditional Trading Orders with Tradevest

This guide describes the **happy-path process** of placing **traditional trading orders** using the Tradevest API in the situation where partners already onboarded natural persons and provided them with the trading profiles and funds available for trading. It also refers to the completion of regulatory requirements.

The process of placing traditional trading orders is not just about creating different types of orders, but also about getting corresponding documents such as trade invoices or ex-ante receipts.

The Tradevest API is **asynchronous by design**. Most create or update operations return either a UUID or an HTTP success status immediately. The current state of a resource can be retrieved at any time via the corresponding `GET` endpoints. In addition, Tradevest emits webhook notifications for relevant lifecycle events.

### Overview of required steps

1. Get available assets (`GET /traditional/assets`)
2. Get Ex-Ante receipt pre trade
   1. POST (`POST /traditional/ex-ante`)
   2. GET (`GET /traditional/ex-ante`)
3. Create Order
   1. Market
      1. POST (`POST /traditional/orders/market`)
      2. GET (`GET /traditional/orders/market`)
   2. Limit
      1. POST (`POST /traditional/orders/limit`)
      2. GET (`GET /traditional/orders/limit`)
   3. Stop
      1. POST (`POST /traditional/orders/stop`)
      2. GET (`GET /traditional/orders/stop`)
   4. Order Cancellation (`DELETE /traditional/orders/{orderId}`)
   5. Account balances flow
4. Get Order Documents and Fee details
   1. Ex-Ante post-trade (`GET /traditional/ex-ante`)
   2. Trade Invoice (`GET /traditional/orders/trade-invoice`)
   3. Key Information Document (`GET /traditional/assets/{isin}/document`)
5. Get Transactions (`GET /customers/{customerId}/transactions?limit=20`) & Get Transaction (`GET /transactions/{transactionId}`)
6. Get Traditional Assets Changelog (`GET /traditional-changelog?itemId={orderId}&ChangelogItemType=ORDER`)

### Order Types

There are 3 order types, which are currently available:

1. Market order - executes immediately at the best available current market price. Guarantees execution (if liquidity exists) but carries risk of slippage in volatile markets.
2. Limit order - executes only at the specified price or better (lower for buy, higher for sell). Guarantees price control but offers no guarantee of execution if the market does not reach the limit.
3. Stop order - remains dormant until the market hits a trigger price. Once triggered, it converts into a Market Order. Used primarily for "Stop Loss" (exiting) or "Stop Entry" (entering) strategies; execution price may differ from the trigger price due to market gaps.

## 0. Prerequisites

### Webhook Event

Before proceeding with traditional trading, ensure that webhook subscriptions are configured for the following event types, which are required to monitor and track the lifecycle of the whole trading chain:

* `TRADITIONAL_ASSET_ORDER_NOTIFICATION`
* `CORPORATE_ACTION_NOTIFICATION`

Webhook notifications are strongly recommended. If webhooks are not configured, partners must actively poll the corresponding `GET` endpoints to retrieve status updates. Please note that detailed error reasons are only returned via webhook notifications.

Refer to the [**API Reference - Webhooks**](https://docs.tradevest.ai/api-reference/webhooks) section for instructions on how to create, update, and delete webhook subscriptions, and to the [**Partner Webhooks**](https://docs.tradevest.ai/api-reference/webhooks) section for details on webhook payloads.

### Tradevest API entities for traditional orders

Before placing the first trade, it is essential to understand the core entities that constitute the Tradevest platform. These components work together to ensure regulatory compliance, secure asset custody, and partner-specific trading logic. The below entities must be fully established to enable order execution.

**1. Customer that has been onboarded**

**2. Depository & balance accounts that are created for customer**

**3. Trading Profile that has been added to Natural Person**

**4. Funds are available on the bank account**

## 1. Get available assets

Before placing an order, it is necessary to identify the specific financial instrument (asset) intended for trading. This step ensures that the asset is available within the Tradevest ecosystem, verifies its risk classification and provide some key details on particular securities like `assetName` or `assetType`.

The following business rules are to be considered for the implementation:

* **Asset Identification:** Instruments are uniquely identified using the `isin` or `wkn` parameters.
* **Trading Availability:** Only assets with `tradingStatus: ACTIVE` on at least one exchange are eligible for order placement.
* **Fractional Trading Constraints:** If `fractionalTrading` is set to `false`, only orders with integer quantities (whole shares) are accepted. **Important Note:** Fractional share trading is **not yet available** through the Tradevest API. Ensure that the `fractionalTrading` flag (if applicable in your configuration) is set to `false`, as only orders for whole shares will be accepted and processed at this time.

**Request**

```http
GET /traditional/assets
```

**Exemplary response for `isin` = DE000A1EWWW0 on `exchangeCode` = TGAT**

```json
200 OK

{
    "data": [
        {
            "isin": "DE000A1EWWW0",
            "wkn": "A1EWWW",
            "assetName": "adidas AG",
            "assetType": "EQUITY",
            "assetRiskScore": "2",
            "fractionalTrading": false,
            "exchanges": [
                {
                    "exchangeCode": "TGAT",
                    "tradingStatus": "ACTIVE"
                }
            ]
        }
    ],
    "pagination": {
        "cursor": "",
        "limit": 1
    }
}
```

The response provides asset metadata along with a list of supported exchanges and their current trading statuses.

## 2. Get Ex-Ante receipt pre trade

#### Ex-Ante Cost Estimation

Before finalizing any traditional trading order, an **Ex-Ante Cost Estimation** must be generated and presented to the customer. This provides a transparent, non-binding breakdown of all costs associated with the transaction, including service fees and product charges.

**Additional notes to the above**

To ensure regulatory compliance, the following integration steps are mandatory:

* **Mandatory Data Presentation:** Partners **must** call the `POST /traditional/ex-ante` endpoint. The returned data must be displayed clearly in the UI to the customer before they confirm the order.
* **PDF Generation:** While the data must always be shown, the generation of a formal PDF document is **optional** and should only be triggered if the customer explicitly requests it
* **No Storage Policy:** To ensure data accuracy and compliance, this document **must NOT be stored** on the partner's servers. It is a real-time estimation intended for immediate presentation only.

The following business rules are to be considered for the implementation:

* **Regulatory Compliance:** Generating and displaying this receipt is mandatory under MiFID II regulations before the customer commits to the trade.
* **Price Requirement:** For `MARKET` orders, the price is estimated based on current market data. For `LIMIT` or `STOP` orders, the specific `price` parameter must be provided to calculate costs accurately.
* **Validity:** The `exAnteId` returned in the response is a unique identifier for the specific cost calculation and may be required during the order placement step to ensure the customer has seen the correct estimates.

#### Generate Ex-Ante Estimation

To retrieve the cost breakdown data, a POST request is sent with the intended order parameters.

**Request**

```json
POST /traditional/ex-ante

{
    "tradeSide": "BUY",
    "quantityType": "UNIT",
    "exchangeCode": "TGAT",
    "orderType": "MARKET",
    "isin": "DE0007010803",
    "quantity": 1
}
```

**Response**

The response returns a structured breakdown of all transaction-related costs and a unique `exAnteId`.

```json
200 OK

{
    "exAnteId": "e8402383-edac-42c8-bdd6-1d5ecc1b6ae6",
    "createdOn": "2025-08-08T12:06:21.046312852Z",
    "asset": {
        "isin": "DE0007010803",
        "type": "EQUITY",
        "name": "RATIONAL AG"
    },
    "order": {
        "quantity": "1",
        "tradeSide": "BUY",
        "exchangeCode": "TGAT",
        "grossAmount": "654.5",
        "pricePerUnit": "654.5",
        "currency": "EUR"
    },
    "costs": [
        {
            "category": "PURCHASE",
            "type": "TRANSACTION",
            "value": "1000",
            "percent": "152.78838808250573",
            "currency": "EUR"
        },
        {
            "category": "HOLDING",
            "type": "PRODUCT",
            "value": "0",
            "percent": "0",
            "currency": "EUR"
        },
        {
            "category": "SALE",
            "type": "TRANSACTION",
            "value": "1000",
            "percent": "152.78838808250573",
            "currency": "EUR"
        }
    ],
    "total": {
        "productCosts": {
            "currency": "EUR",
            "ter": "0",
            "percent": "0"
        },
        "transactionFees": {
            "currency": "",
            "feeAmount": "2000",
            "percent": "305.57677616501146"
        },
        "grants": {
            "currency": "EUR",
            "grantsAmount": "0",
            "percent": "0"
        }
    },
    "timeline": {
        "year1": {
            "currency": "EUR",
            "feeAmount": "1000",
            "percent": "152.78838808250573"
        },
        "fromYear2": {
            "currency": "EUR",
            "ter": "0",
            "percent": "0"
        },
        "yearOfSale": {
            "currency": "EUR",
            "feeAmount": "1000",
            "percent": "152.78838808250573"
        }
    },
    "metaInfo": {
        "disclaimer": "All values are based on real-time data and are non-binding estimates, assuming a holding period of five years.",
        "explanation": "Transaction fees include execution costs; TER applies only to ETFs."
    }
}
```

#### Download Ex-Ante PDF Document

This endpoint returns the formal Ex-Ante Cost Estimation as a document.

**Response**

The API returns a JSON object containing a raw Base64 encoded string representing the PDF file.

Handling the response: To display or download the document in a web browser or a mobile frontend, use the Data URI scheme. You can directly embed the PDF or open it in a new tab by prepending the standard PDF prefix to the response string:

`data:application/pdf;base64,{BASE64_STRING}`

## 3. Create Orders

This section describes the process of placing traditional trading orders through the Tradevest API. Placing an order is the central action of the trading lifecycle, following the mandatory retrieval of an Ex-ante cost estimation.

The Tradevest API supports three primary order types described and distinguished above:

* **Market Order**: Executes immediately at the current prevailing market price.
* **Limit Order**: Executes only at a specified price or better.
* **Stop Order**: Triggered when the market price reaches a specified stop price.

The following business rules are to be considered for the implementation:

* **Required Product Identifiers**: Every order requires both a `depositoryCustomerProductId` (where assets are held) and a `cashCustomerProductId` (where funds are drawn from or deposited to).
* **Asynchronous Processing**: The initial `POST` request returns an acknowledgment with a unique `orderId`. The execution progress (e.g., from `PLACED` to `FILLED`) must be monitored via `GET` requests or webhooks.
* **Partial Executions**: An order may be executed in multiple parts. These are reflected in the `partialExecutions` array in the order details. This endpoint returns the formal Ex-Ante Cost Estimation as a document for each order.

#### a. Market Orders

Market orders are used for immediate execution when the priority is the speed of the trade rather than a specific price. It is important to mention that there is an additional buffer of 10% on top of the market price, covering the price slippage during execution.

**Request**

```json
POST /traditional/orders/market

{
    "depositoryCustomerProductId": "{{customerProductId_DEPOSITORY_ACCOUNT}}",
    "cashCustomerProductId": "{{customerProductId_BALANCE_ACCOUNT}}",
    "tradeSide": "BUY",
    "quantityType": "UNIT",
    "exchangeCode": "TGAT",
    "isin": "NO0003054108",
    "quantity": 10,
    "externalId": "{{externalId_marketOrder}}"
}
```

**Response**

```json
200 OK
{
    "orderId": "df85e7fb-28ab-4239-80e2-3e633ffde253",
    "createdOn": "2026-02-26T09:09:06.03397151Z"
}
```

#### Retrieve market order

In order to retrieve market order details send the following request.

**Request**

```http
GET /traditional/orders/{orderId}
```

**Response**

The response below includes detailed information about the market order execution. Beyond the standard timestamps, the following system-generated fields and objects are critical for tracking the transaction:

* **status**: Reflects the current state of the order in the Tradevest system (e.g., `RECEIVED`, `PLACED`, `FILLED`, or `REJECTED`).
* **execution**: This object is populated once the order reaches the `FILLED` or `PARTIALLY_FILLED` status. It contains the aggregate data of the trade, including the `executionPrice` and the total `amount`.
* **partialExecutions**: A list of individual trade events. In traditional trading, a single order may be filled through multiple smaller trades on the exchange; each is recorded here with its own `executionId`.
* **valueDate & bookingDate**: Standard financial dates. The `valueDate` is the date as of which the asset value is considered, while the `bookingDate` is the date when the final cash settlement occurs.
* **feeAmount & feeDescription**: Details regarding the transaction costs applied to this specific order based on the partner's fee configuration.

```json
200 OK

{
    "orderId": "df85e7fb-28ab-4239-80e2-3e633ffde253",
    "exAnteId": "53e143d7-9f0b-4ab6-a21b-e60471dfba1e",
    "createdOn": "2026-02-26T09:09:06.033971Z",
    "modifiedOn": "2026-02-26T09:09:08.643376Z",
    "status": "FILLED",
    "message": "",
    "execution": {
        "executionPrice": "16.79",
        "executionQuantity": "10",
        "valueDate": "2026-02-26",
        "bookingDate": "2026-03-02",
        "transactionTime": "2026-02-26T09:09:07.926423Z",
        "amount": "167.9",
        "feeAmount": "4",
        "feeDescription": "feeInstanceId 6c154d19-c157-4784-bc02-87657099fcb9 for order",
        "germanCit": "0",
        "solidaritySurcharge": "0",
        "churchTax": "0",
        "amountCurrency": "EUR"
    },
    "partialExecutions": [
        {
            "executionId": "f4cead59-dedd-4b0c-b73b-663929696937",
            "executionPrice": "16.79",
            "executionQuantity": "10",
            "amount": "167.9",
            "executionTime": "2026-02-26T09:09:07.926423Z",
            "valueDate": "2026-02-26",
            "bookingDate": "2026-03-02",
            "status": "FILLED",
            "feeAmount": "4",
            "feeDescription": "feeInstanceId 6c154d19-c157-4784-bc02-87657099fcb9 for order"
        }
    ],
    "depositoryCustomerProductId": "fb0d02ca-7186-46dd-963c-f06eba6bc6ac",
    "cashCustomerProductId": "d3d793f8-5d37-4750-81da-31f05c354134",
    "tradeSide": "BUY",
    "isin": "NO0003054108",
    "quantity": "10",
    "orderType": "MARKET",
    "quantityType": "UNIT",
    "expiryDate": "2026-02-26",
    "externalId": "33e14859-4465-4497-96a2-e90d515fdeaa",
    "exchangeCode": "TGAT"
}
```

There is also an additional endpoint that allows you to retrieve a comprehensive list of traditional orders associated with a specific depository account. It is designed to facilitate order monitoring and history retrieval through extensive filtering options.

#### b. Limit Orders

Limit orders specify the maximum price to be paid for a BUY trade or the minimum price to be accepted for a SELL trade. The general flow for placing orders and retrieving execution data is the same.

Business Rules for Limit Orders:

* **Price Precision:** The `limitPrice` must be specified and supports a fractional value with up to 3 decimal places.
* **Quantity Constraints:** Only full units (integers) can be traded, fractional quantities are not supported for limit orders.
* **Validation & Position:** The system validates sufficient funds for BUY trades or sufficient asset positions for SELL trades. Short selling is strictly prohibited.
* **Funds Blocking:** For BUY orders, funds are blocked immediately upon placement. The blocked amount equals `(quantity * limitPrice) + fees`.
* **Duration of Block:** Blocked funds or assets remain reserved as long as the order status is active (`PLACED` or `PENDING`) and are only released upon full execution (`FILLED`), cancellation (`CANCELLED`), expiration (`EXPIRED`) or partially executed terminated states (`PARTIALLY_FILLED_CANCELLED`) and (`PARTIALLY_FILLED_EXPIRED`). In addition, `expiryDate` must be provided once submitting the order.

Let us analyse the basic differences on the same ISIN = NO0003054108, which was executed at a market price of 16.79 EUR in the above market order placement example.

#### Scenario 1 - Limit Order with the price lower than currently quoted on the market

If a BUY limit order is placed with a `limitPrice`: 16.111 EUR while the current market price is **16.79 EUR**, the order will be transmitted to the exchange but will not execute immediately.

**Request**

```json
POST /traditional/orders/limit

{
    "depositoryCustomerProductId": "{{customerProductId_DEPOSITORY_ACCOUNT}}",
    "cashCustomerProductId": "{{customerProductId_BALANCE_ACCOUNT}}",
    "tradeSide": "BUY",
    "quantityType": "UNIT",
    "exchangeCode": "TGAT",
    "isin": "NO0003054108",
    "quantity": 10,
    "limitPrice": 16.111,
    "expiryDate": "{{currentDate}}",
    "externalId": "{{externalId_limitOrder}}"
}
```

**Response**

```json
200 OK

{
    "orderId": "2e80a5a5-42ae-4f9f-b374-baa71ef93cfa",
    "createdOn": "2026-02-26T09:56:50.417252499Z"
}
```

**Retrieve limit order**

```http
GET /traditional/orders/{orderId}
```

```json
200 OK

{
    "orderId": "2e80a5a5-42ae-4f9f-b374-baa71ef93cfa",
    "exAnteId": "8b34f825-5ef2-422d-a321-48d43d7c1dd7",
    "createdOn": "2026-02-26T09:56:50.417252Z",
    "modifiedOn": "2026-02-26T09:56:52.761517Z",
    "status": "PLACED",
    "message": "",
    "depositoryCustomerProductId": "fb0d02ca-7186-46dd-963c-f06eba6bc6ac",
    "cashCustomerProductId": "d3d793f8-5d37-4750-81da-31f05c354134",
    "tradeSide": "BUY",
    "isin": "NO0003054108",
    "quantity": "10",
    "orderType": "LIMIT",
    "quantityType": "UNIT",
    "limitPrice": "16.111",
    "expiryDate": "2026-02-26",
    "externalId": "cf6935b4-2e48-49c7-892a-3f93a90e8024",
    "exchangeCode": "TGAT"
}
```

As shown in the example above, the order status remains **PLACED**. This indicates that the order is active on the exchange (Tradegate) but is waiting for the market price to drop to **16.111 EUR** or lower.

From a balance management perspective, although no shares have been purchased yet, the required capital is already **blocked** on the cash account. This ensures that the funds are available the moment the market conditions meet the limit criteria. The order will only transition to **FILLED** once a matching trade occurs on the exchange, at which point the final settlement occurs.

#### Scenario 2 - Limit Order with the price higher than currently quoted on the market

In this scenario, a BUY limit order is placed with a `limitPrice` of **18 EUR**, while the current market price remains lower.

**Request**

```json
POST /traditional/orders/limit

{
    "depositoryCustomerProductId": "{{customerProductId_DEPOSITORY_ACCOUNT}}",
    "cashCustomerProductId": "{{customerProductId_BALANCE_ACCOUNT}}",
    "tradeSide": "BUY",
    "quantityType": "UNIT",
    "exchangeCode": "TGAT",
    "isin": "NO0003054108",
    "quantity": 10,
    "limitPrice": 18,
    "expiryDate": "{{currentDate}}",
    "externalId": "{{externalId_limitOrder}}"
}
```

**Response**

```json
200 OK

{
    "orderId": "5271fc31-3c43-402e-b4b0-e242b4695fb9",
    "createdOn": "2026-02-26T10:07:57.8108426Z"
}
```

**Retrieve limit order**

```http
GET /traditional/orders/{orderId}
```

```json
200 OK

{
    "orderId": "5271fc31-3c43-402e-b4b0-e242b4695fb9",
    "exAnteId": "88654cba-d05c-4a7b-be93-7cf87447c9d3",
    "createdOn": "2026-02-26T10:07:57.810842Z",
    "modifiedOn": "2026-02-26T10:08:02.207845Z",
    "status": "FILLED",
    "message": "",
    "execution": {
        "executionPrice": "17.59",
        "executionQuantity": "10",
        "valueDate": "2026-02-26",
        "bookingDate": "2026-03-02",
        "transactionTime": "2026-02-26T10:08:01.30216Z",
        "amount": "175.9",
        "feeAmount": "4",
        "feeDescription": "feeInstanceId 6c154d19-c157-4784-bc02-87657099fcb9 for order",
        "germanCit": "0",
        "solidaritySurcharge": "0",
        "churchTax": "0",
        "amountCurrency": "EUR"
    },
    "partialExecutions": [
        {
            "executionId": "514913e9-4994-4851-a44c-087ca2b2fa3e",
            "executionPrice": "17.59",
            "executionQuantity": "10",
            "amount": "175.9",
            "executionTime": "2026-02-26T10:08:01.30216Z",
            "valueDate": "2026-02-26",
            "bookingDate": "2026-03-02",
            "status": "FILLED",
            "feeAmount": "4",
            "feeDescription": "feeInstanceId 6c154d19-c157-4784-bc02-87657099fcb9 for order"
        }
    ],
    "depositoryCustomerProductId": "fb0d02ca-7186-46dd-963c-f06eba6bc6ac",
    "cashCustomerProductId": "d3d793f8-5d37-4750-81da-31f05c354134",
    "tradeSide": "BUY",
    "isin": "NO0003054108",
    "quantity": "10",
    "orderType": "LIMIT",
    "quantityType": "UNIT",
    "limitPrice": "18",
    "expiryDate": "2026-02-26",
    "externalId": "ca5810d6-d79d-4573-981a-2a5e86d4c480",
    "exchangeCode": "TGAT"
}
```

As demonstrated in Scenario 2, the order status transitions almost immediately to **FILLED**. This occurs because the `limitPrice` for a BUY order represents the **maximum** price a user is willing to pay. Since the available market price (**17.59 EUR**) is lower (better) than the specified limit (**18 EUR**), the exchange executes the trade immediately at the best available price.

Key takeaways for balance and order management:

* **Immediate Fill:** Unlike Scenario 1, the order does not stay in the `PLACED` state because the market conditions already satisfy the limit criteria.
* **Balance Impact:** The system initially blocks funds based on the `limitPrice` (18.00 EUR), but upon immediate execution, the actual debited amount is adjusted to reflect the real `executionPrice` plus fees. Any excess blocked funds are released back to the available balance immediately after the status changes to `FILLED`.

The scenarios described above illustrate the logic for **BUY** orders. The same business logic and technical workflow apply to **SELL** orders, where the `limitPrice` represents the **minimum** price at which the asset should be sold. In a SELL scenario, if the market price is already higher than the `limitPrice`, the order will result in immediate execution (Price Improvement), similar to Scenario 2.

#### c. Stop Orders

A stop order is an instruction to buy or sell an asset once the market price reaches a specific level, known as the **stop price**.

* For a **BUY stop order**, the trade is triggered when the market price rises to the stop price.
* For a **SELL stop order**, the trade is triggered when the market price falls to the stop price.

Stop orders are primarily used to enter or exit positions when the market moves to a certain level. However, there is no guarantee the order will be filled at the exact stop price due to market volatility or price gaps.

**Business Rules for Stop Orders:**

* **Price Precision:** The `stopPrice` must be specified.
* **Quantity Constraints:** Only full units (integers) can be traded. Fractional quantities are not supported.
* **Validation & Position:** The system validates sufficient funds for BUY trades or sufficient asset positions for SELL trades. Short selling is prohibited.
* **Funds Blocking:** For BUY orders, funds are blocked immediately upon placement. The blocked amount equals exactly `(quantity * stopPrice) + security buffer + fees`.
* **Duration of Block:** Blocked funds remain reserved as long as the stop order is valid (`PLACED` or `PENDING`) and are released upon execution (`FILLED`) or cancellation (`CANCELLED`). In addition, `expiryDate` must be provided once submitting the order.

#### Scenario 1 - Stop Order with the price lower than currently quoted on the market

If a BUY stop order is placed with a `stopPrice` of **16 EUR** while the market price is already higher (e.g., **17.24 EUR**), the trigger condition is immediately met.

**Request**

```json
{
    "depositoryCustomerProductId": "{{customerProductId_DEPOSITORY_ACCOUNT}}",
    "cashCustomerProductId": "{{customerProductId_BALANCE_ACCOUNT}}",
    "tradeSide": "BUY",
    "quantityType": "UNIT",
    "exchangeCode": "TGAT",
    "isin": "NO0003054108",
    "quantity": 10,
    "stopPrice": 16,
    "expiryDate": "2026-02-26",
    "externalId": "{{externalId_stopOrder}}"
}
```

**Response**

```json
200 OK

{
    "orderId": "42e90e09-1ad1-4f32-ac05-f4a56e93fbd7",
    "createdOn": "2026-02-26T10:21:44.691Z"
}
```

**Retrieve stop order**

```http
GET /traditional/orders/stop/{orderId}
```

```json
{
    "orderId": "42e90e09-1ad1-4f32-ac05-f4a56e93fbd7",
    "exAnteId": "6e842a45-06d3-447a-b2bc-c996ec407545",
    "createdOn": "2026-02-26T10:21:44.691079Z",
    "modifiedOn": "2026-02-26T10:21:46.854609Z",
    "status": "FILLED",
    "message": "",
    "execution": {
        "executionPrice": "17.24",
        "executionQuantity": "10",
        "valueDate": "2026-02-26",
        "bookingDate": "2026-03-02",
        "transactionTime": "2026-02-26T10:21:46.605977Z",
        "amount": "172.4",
        "feeAmount": "4",
        "feeDescription": "feeInstanceId 6c154d19-c157-4784-bc02-87657099fcb9 for order",
        "germanCit": "0",
        "solidaritySurcharge": "0",
        "churchTax": "0",
        "amountCurrency": "EUR"
    },
    "partialExecutions": [
        {
            "executionId": "386debec-382a-480b-bf32-ffa840a75a95",
            "executionPrice": "17.24",
            "executionQuantity": "10",
            "amount": "172.4",
            "executionTime": "2026-02-26T10:21:46.605977Z",
            "valueDate": "2026-02-26",
            "bookingDate": "2026-03-02",
            "status": "FILLED",
            "feeAmount": "4",
            "feeDescription": "feeInstanceId 6c154d19-c157-4784-bc02-87657099fcb9 for order"
        }
    ],
    "depositoryCustomerProductId": "fb0d02ca-7186-46dd-963c-f06eba6bc6ac",
    "cashCustomerProductId": "d3d793f8-5d37-4750-81da-31f05c354134",
    "tradeSide": "BUY",
    "isin": "NO0003054108",
    "quantity": "10",
    "orderType": "STOP",
    "quantityType": "UNIT",
    "stopPrice": "16",
    "expiryDate": "2026-02-26",
    "externalId": "92d19000-b36e-4015-b28e-c00a8e5b9958",
    "exchangeCode": "TGAT"
}
```

Because the market price was already above the stop trigger, the order transitions immediately to **FILLED**. The `executionPrice` (**17.24 EUR**) reflects the current market rate at the moment of triggering.

#### Scenario 2 - Stop Order with the price higher than currently quoted on the market

In this scenario, a BUY limit order is placed with a `stopPrice` of **18 EUR**, while the current market price remains lower.

**Request**

```json
{
    "depositoryCustomerProductId": "{{customerProductId_DEPOSITORY_ACCOUNT}}",
    "cashCustomerProductId": "{{customerProductId_BALANCE_ACCOUNT}}",
    "tradeSide": "BUY",
    "quantityType": "UNIT",
    "exchangeCode": "TGAT",
    "isin": "NO0003054108",
    "quantity": 10,
    "stopPrice": 18,
    "expiryDate": "{{currentDate}}",
    "externalId": "{{externalId_stopOrder}}"
}
```

**Response**

```json
200 OK

{
    "orderId": "3f93fd2d-ad0b-4554-ba32-fa700e2b4c46",
    "createdOn": "2026-02-26T10:33:23.390106797Z"
}
```

**Retrieve stop order**

```http
GET /traditional/orders/stop/{orderId}
```

```json
200 OK

{
    "orderId": "3f93fd2d-ad0b-4554-ba32-fa700e2b4c46",
    "exAnteId": "c2cc5f0a-e06b-4a2d-9436-edcd34db62fd",
    "createdOn": "2026-02-26T10:33:23.390106Z",
    "modifiedOn": "2026-02-26T10:33:27.887554Z",
    "status": "PLACED",
    "message": "",
    "depositoryCustomerProductId": "fb0d02ca-7186-46dd-963c-f06eba6bc6ac",
    "cashCustomerProductId": "d3d793f8-5d37-4750-81da-31f05c354134",
    "tradeSide": "BUY",
    "isin": "NO0003054108",
    "quantity": "10",
    "orderType": "STOP",
    "quantityType": "UNIT",
    "stopPrice": "18",
    "expiryDate": "2026-02-26",
    "externalId": "a5e5333a-0e8a-49e1-943a-b64bdfd4789b",
    "exchangeCode": "TGAT"
}
```

Because the market price was already above the stop trigger, the order transitions immediately to **FILLED**. The `executionPrice` (**17.24 EUR**) reflects the current market rate at the moment of triggering.

The examples demonstrate that a stop order acts as a "threshold trigger." In **Scenario 1**, the threshold was already surpassed by the market, leading to an immediate market execution. In **Scenario 2**, the order remains dormant on the exchange until the price rises to the specified level.

Unlike limit orders, which guarantee a price but not execution, a triggered stop order guarantees execution (as a market order) but does not guarantee the exact `stopPrice`. Funds remain blocked at the target rate to ensure settlement capability once the market reaches the desired momentum.

The examples provided above focus on **BUY** stop orders (often used to enter a position on a breakout). It is important to note that the same logic applies to **SELL** stop orders (commonly used as "Stop-Loss" protection). For a SELL stop order, the trade is triggered when the market price **falls** to or below the specified `stopPrice`. Just as with BUY orders, the system ensures asset availability before placement and handles the transition from `PLACED` to `FILLED` automatically once the price threshold is reached.

#### d. Order Cancellation

The Tradevest API provides a dedicated endpoint to cancel orders that have not yet been executed. Cancellation is primarily applicable to **Limit** and **Stop** orders that are in the `PLACED` status. While theoretically possible for **Market** orders, the immediate nature of their execution means they rarely remain in a cancellable state.

**Business Rules for Order Cancellation:**

* **Eligibility:** Only orders with the status `PLACED` or `PARTIALLY_FILLED` can be cancelled. Once an order is `FILLED`, `REJECTED`, or `EXPIRED`, cancellation is no longer possible.
* **Funds Release:** Upon successful cancellation of a BUY order, the previously blocked funds (including the security buffer) are immediately released back to the customer's available cash balance.
* **Asset Release:** For a CANCELLED sell order, the reserved assets are released and become available for new transactions in the depository.

**Request**

To initiate a cancellation, a DELETE request is sent using the unique `orderId`.

`DELETE /traditional/orders/{orderId}`

**Response**

The request returns an immediate acknowledgment.

#### Verifying Cancellation via Retrieve Order

After a successful cancellation, querying the order details via the `GET /traditional/orders/{orderId}` endpoint will show the updated terminal status. The `status` field transitions to `CANCELLED`, and the `message` field typically reflects the reason for the state change.

The cancellation event is also recorded as a permanent entry in the **Traditional Assets Changelog**. This provides a full audit trail showing the transition from `PLACED` to `CANCELLED`/`PARTIALLY_FILLED_CANCELLED` or from `PARTIALLY_FILLED` to `PARTIALLY_FILLED_CANCELLED`, triggered by an `INTERNAL_CHANGE` or user action. It can be retrieved via the endpoint `GET /traditional-changelog?itemId={orderId}&ChangelogItemType=ORDER`

#### e. Account balances flow

The account balance flow in traditional trading describes how funds are moved between various internal and customer accounts to ensure regulatory compliance, tax handling, and final settlement. Tradevest utilizes a real-time booking system for internal transfers.

**Key Concepts**

* **T+0 (Execution Day):** Real-time processing of trade executions and creation of internal transaction available via the `GET /transactions/{transactionId}` endpoint.
* **T+2/T+3 (Settlement):** The period during which final funds are moved between bank accounts and settlement is finalized.
* **Blocked Funds:** A temporary hold placed on a customer's cash account to ensure sufficient funds for an order.

**BUY Flow**

When a purchase is initiated, the system must secure the funds before transmitting the order to the exchange.

**Order Placement (Initial Blocking):**

* Before the order is sent to **Tradegate**, a **BLOCK** transaction is created for the estimated order amount + 10% security buffer.

**Execution (Per Fill):**

* Unblocking: For each execution received, an UNBLOCK transaction is triggered for the `execution amount + fee`.

**SELL FLOW**

The sell flow focuses on distributing the proceeds from a trade to the customer while withholding necessary fees and taxes.

**T=0 (Immediate Execution Processing):**

* Transactions are being created.

**T+3 (Final Settlement):**

* A scheduled job executes the actual fund movements and the funds will be transferred to the customers virtual IBAN account.
* Funds move from the **Settlement Account** to the respective **Fee**, **Tax**, and **Customer** bank accounts.

## 4. Get Order Documents and Fee details

#### a. Ex-Ante post-trade

After an order is successfully executed (status `PENDING` or `PLACED`), the Tradevest system generates post-trade documents. These documents are essential for record-keeping, tax reporting, and regulatory compliance.

**Request**

`GET /traditional/ex-ante/{exAnteId}` & `GET /v2/documents/{documentId}/file`

**Response**

Similar to other documents, the response returns a **Base64-encoded PDF** string prefixed with the Data URI scheme for immediate browser rendering.

The generated document includes the following detailed information:

* **Identification Data:** Client name, address, and depository number.
* **Transaction Details:** Asset name, ISIN, transaction type (*Wertpapierkauf*), and the exchange code (e.g., *TGAT*).
* **Cost Summary:** **One-off Entry/Exit Costs:** A breakdown of product and service costs (*Dienstleistungskosten*) in both EUR and percentage.
  * **Ongoing Costs:** Costs associated with holding the asset per year.
* **Impact on Returns:** A detailed table illustrating how cumulative costs affect the expected investment return over time (e.g., a 5-year horizon).

#### b. Trade Invoice

The **Trade Invoice** (also referred to as *Wertpapierabrechnung*) provides the final tax and accounting breakdown for a specific execution. This document is essential for tax reporting and as an official record of the transaction's financial settlement.

**Request**

`GET /v2/documents/{documentId}/file` & `GET /traditional/orders/trade-invoice/{executionId}`

**Response**

The endpoint returns a **Base64-encoded PDF** string within a JSON object, formatted for direct use in the Data URI scheme.

The invoice contains the following key sections:

* **Transaction Summary:** Details the asset (e.g., *Mowi ASA*), transaction type (*Verkauf*), quantity, and market price per unit.
* **Financial Calculation:** Specifies the market value (*Kurswert*), applied commission (*Provision*), tax deductions (*Steuerabzug*), and the final net amount to be credited or debited.
* **Settlement Information:** Includes the value date (*Valuta*), booking date, and the specific account identifier where the funds will be settled.
* **Tax Basis for SELL orders:** Provides the detailed tax calculation basis (*Steuerliche Berechnungsgrundlage*), including capital gains, applicable surcharges (e.g., *Solidaritätszuschlag*), and any church taxes.

#### c. Key Information Documents

For ETFs the platform provides access to the Key Information Document (KID), a standardized pre-contractual disclosure document.

**Response**

`GET /traditional/assets/{isin}/document`

Path Variables:

* `isin` - ISIN of the asset for which the document is requested.

Query Parameters:

* `language` - language of the document (`de` / `en`).
* `documentType` - type of document to retrieve (`kid`).

The response returns a Base64-encoded PDF string, formatted for direct use in the Data URI scheme.

## 5. Get Transactions

The Transactions endpoint provides a detailed financial view of completed or pending operations. While the Orders endpoint focuses on the intent and execution status on the exchange, the Transactions endpoint consolidates trading data with settlement and accounting information, such as specific booking dates and tax breakdowns.

The following business rules are to be considered for the implementation:

* **Transaction ID vs Order ID:** For trading operations, the `transactionId` usually corresponds to the `orderId`, but it represents the record in the customer's financial ledger.
* **Transaction Types:** This endpoint covers various movements, but for traditional trading, the `transactionType` will be labeled as `TRADE`.
* **Settlement Dates:** It distinguishes between the `valueDate` (the date the economic transition occurs) and the `bookingDate` (the date the cash is officially settled on the account).
* **Detailed Execution Data:** Unlike the standard order response, transactions provide a nested `executionData` object that includes finalized fees and tax placeholders (e.g., `germanCit`, `solidaritySurcharge`).

#### Retrieve Transaction Details

To retrieve the comprehensive details of a specific transaction, use the `orderId`.

**Request**

`GET /customers/{customerId}/transactions?limit=20`

**Response**

The response provides a high-level transaction status combined with a detailed `traditionalTradingTransaction` object containing the full execution history. Below is the example of the response for market order, but the scheme applies to all types of the trading orders.

```json
200 OK

{
    "transactionId": "df85e7fb-28ab-4239-80e2-3e633ffde253",
    "customerId": "dab4a6f0-1110-483a-bd43-31ad057401e3",
    "createdOn": "2026-02-26T09:09:06.033971Z",
    "modifiedOn": "2026-02-26T09:09:08.643376Z",
    "transactionType": "TRADE",
    "transactionStatus": "COMPLETED",
    "bookingDate": "2026-03-02",
    "valueDate": "2026-02-26",
    "traditionalTradingTransaction": {
        "orderId": "df85e7fb-28ab-4239-80e2-3e633ffde253",
        "depositoryCustomerProductId": "fb0d02ca-7186-46dd-963c-f06eba6bc6ac",
        "cashCustomerProductId": "d3d793f8-5d37-4750-81da-31f05c354134",
        "isin": "NO0003054108",
        "exchangeCode": "TGAT",
        "assetType": "EQUITY",
        "tradeSide": "BUY",
        "quantityType": "UNIT",
        "quantity": "10",
        "currency": "EUR",
        "orderType": "MARKET",
        "expiryDate": "2026-02-26",
        "orderStatus": "FILLED",
        "externalId": "33e14859-4465-4497-96a2-e90d515fdeaa",
        "executionData": {
            "quantity": "10",
            "executionPrice": "16.79",
            "executionAmount": "167.9",
            "feeDescription": "feeInstanceId 6c154d19-c157-4784-bc02-87657099fcb9 for order",
            "feeAmount": "4",
            "germanCit": "0",
            "solidaritySurcharge": "0",
            "churchTax": "0"
        },
        "partialExecutions": [
            {
                "executionId": "f4cead59-dedd-4b0c-b73b-663929696937",
                "executionPrice": "16.79",
                "executionQuantity": "10",
                "amount": "167.9",
                "executionTime": "2026-02-26T09:09:07.926423Z",
                "valueDate": "2026-02-26",
                "bookingDate": "2026-03-02",
                "status": "FILLED"
            }
        ]
    }
}
```

A transaction marked as `COMPLETED` signifies that the trade has been fully processed by the platform internal ledger. However, the actual cash movement in the banking system (e.g., via SEPA) may still be pending until the `bookingDate` is reached. This endpoint is the primary source of truth for generating customer activity statements and history logs.

## 6. Get Traditional Assets Changelog

This endpoint provides a comprehensive audit trail of all modifications and status transitions for a specific trading order. It serves as a historical record for all order types, including **Market**, **Limit**, and **Stop** orders. By querying the changelog, it is possible to track how an order progressed from its initial submission to its final execution or rejection.

The following business rules are to be considered for the usage of this functionality:

* **Order Compatibility:** The changelog is available for any established order ID, regardless of the order type (Stop, Limit, or Market).
* **Change Tracking:** Each entry in the `data` array represents a specific event in time where the order resource was modified.
* **Internal vs. External Sources:** The `source` field distinguishes whether a change was triggered by the partner (`PARTNER_SYSTEM`) or by Tradevest's execution logic (`INTERNAL_CHANGE`).
* **Execution Details:** Significant lifecycle events, such as moving from `PLACED` to `FILLED`, often include more detailed execution metadata (price, quantity, fees) added during the transition.

#### Retrieve Order Changelog

To retrieve the history of a specific order, use the order ID as the `itemId` query parameter.

**Request**

`GET /traditional/traditional-changelog`

**Response**

The response returns an array of entries, each detailing specific field changes (e.g., status updates) and the origin of those changes.

```json
200 OK

{
    "data": [
        {
            "itemType": "ORDER",
            "entryId": "9804fbd1-4e52-4cc8-ae04-950b865ba5fc",
            "itemId": "5ba17ca0-9cf4-4076-80b9-0b62458462b1",
            "createdOn": "2026-02-25T09:46:27.04065966Z",
            "changes": [
                {
                    "type": "REPLACE",
                    "path": "/status",
                    "oldValue": "RECEIVED",
                    "value": "PENDING"
                }
            ],
            "source": "PARTNER_SYSTEM"
        },
        {
            "itemType": "ORDER",
            "entryId": "59d4d58e-5479-4d13-83f8-2775a92ead8e",
            "itemId": "5ba17ca0-9cf4-4076-80b9-0b62458462b1",
            "createdOn": "2026-02-25T09:46:30.869829404Z",
            "changes": [
                {
                    "type": "REPLACE",
                    "path": "/status",
                    "oldValue": "PLACED",
                    "value": "FILLED"
                },
                {
                    "type": "ADD",
                    "path": "/execution",
                    "value": "map[amount:608.2 amountCurrency:EUR executionPrice:60.82 executionQuantity:10 ...]"
                }
            ],
            "source": "INTERNAL_CHANGE"
        }
    ],
    "pagination": {
        "cursor": "",
        "limit": 20
    }
}
```

## 7. Get Asset Document

This endpoint allows the retrieval of official documentation associated with a specific financial instrument, such as the **Key Information Document (KID)**. The document is provided as a Base64-encoded PDF and can be requested in different languages (e.g., English or German).

The following business rules are to be considered for the implementation:

* **Identification:** The asset must be uniquely identified using its `isin`.
* **Language Support:** The optional `language` query parameter allows users to specify the preferred language of the document (supported values: `en`, `de`).
* **Document Format:** The response contains a Base64-encoded string representing the PDF file.
* **Data URI Scheme:** For easy rendering in web browsers or frontend applications, the Base64 string can be used directly with the Data URI prefix: `data:application/pdf;base64,`.

#### Retrieve Asset Documentation

To get the documentation for a specific asset, use the ISIN in the path.

**Request**

`GET /traditional/assets/{{isin}}/document?language=en`

**Response**

The response returns a JSON object containing the `pdf_data_uri_kid`, which includes both the data type prefix and the Base64-encoded content.

## 8. Test Environment - Order Executions scenarios

The test environment allows to simulate the full order lifecycle without real execution. Scenarios are triggered by sending a specific integer value in the `quantity` field (with `quantityType: "UNIT"`) when creating an order via `POST /traditional/orders/{market|limit|stop}`.

**Order lifecycle statuses**

The following statuses are relevant from the Partner API perspective:

| Status                                     | Description                                                   |
| ------------------------------------------ | ------------------------------------------------------------- |
| `RECEIVED`                                 | Order received; moves to `PENDING` in standard flows.         |
| `PENDING`                                  | Order is being processed; may move directly to `REJECTED`.    |
| `PLACED`                                   | Order accepted for execution; most scenarios start from here. |
| `INVALID`                                  | Order failed internal validation; was not sent for execution. |
| `FILLED` / `PARTIALLY_FILLED`              | Fully or partially executed.                                  |
| `CANCELLED` / `PARTIALLY_FILLED_CANCELLED` | Cancelled without or after partial execution.                 |
| `EXPIRED` / `PARTIALLY_FILLED_EXPIRED`     | Expired without or after partial execution.                   |

The `INVALID` status is not quantity-triggered. It occurs when an order fails internal validation - for example, insufficient funds on the Balance Account, insufficient asset quantity on the Depository Account, or mismatched `depositoryCustomerProductId` / `cashCustomerProductId`.

**Recommended test scenarios**

| Test purpose                          | Quantity        | Expected status flow                                     | Final status                 |
| ------------------------------------- | --------------- | -------------------------------------------------------- | ---------------------------- |
| Full execution, single fill           | `1` or `10`     | `PLACED → FILLED`                                        | `FILLED`                     |
| Full execution, multiple fills        | `2`–`8` or `20` | `PLACED → PARTIALLY_FILLED → FILLED`                     | `FILLED`                     |
| Partial execution, order remains open | `30`            | `PLACED → PARTIALLY_FILLED`                              | `PARTIALLY_FILLED`           |
| Partial execution → cancellation      | `32`            | `PLACED → PARTIALLY_FILLED → PARTIALLY_FILLED_CANCELLED` | `PARTIALLY_FILLED_CANCELLED` |
| Partial execution → expiration        | `33`            | `PLACED → PARTIALLY_FILLED → PARTIALLY_FILLED_EXPIRED`   | `PARTIALLY_FILLED_EXPIRED`   |
| Cancellation without execution        | `40`            | `PLACED → CANCELLED`                                     | `CANCELLED`                  |
| Expiration without execution          | `13`            | `PLACED → EXPIRED`                                       | `EXPIRED`                    |
| No execution response (pending)       | `52`            | `PENDING` or `PLACED`                                    | `PENDING` or `PLACED`        |
| GTD - partial fills until expiry      | `80`            | `PLACED → PARTIALLY_FILLED → PARTIALLY_FILLED_EXPIRED`   | `PARTIALLY_FILLED_EXPIRED`   |
| Invalid order                         | Invalid setup   | `RECEIVED → INVALID`                                     | `INVALID`                    |
| Rejected after processing             | Rejection setup | `PENDING → REJECTED`                                     | `REJECTED`                   |

Most quantities also accept multiplied variants (`×10`, `×100`) - for example, `10`, `100`, `1000` all trigger the same full-execution scenario. For high-volume partial-fill testing (1,000–2,000 execution events), use quantity `22`; this should only be used when explicitly testing throughput handling.

**What to verify**

For each scenario, confirm that `orderId` and `externalId` are correctly returned, `status` matches the expected flow, and for partial fills, that executed and remaining quantity values are consistent. For rejected, invalid or cancelled orders, check whether a business reason or message is included in the response.

Note that some scenarios are asynchronous - the order may not have reached its final status by the time the create-order response is returned. Depending on the integration setup, poll the order endpoint or listen for webhook status updates accordingly.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.tradevest.ai/documentation/traditional-trading-orders-with-tradevest.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
