---
title: "Create Manual Order"
method: POST
path: "/api/order/manual/create"
tags: ["Order"]
---

# Create Manual Order

`POST /api/order/manual/create`

## Request

- Base URL: `https://api.desty.app`
- URL: `https://api.desty.app/api/order/manual/create`
- Auth: none declared. Required headers: `Authorization`

## Description

Create a manual order in Desty Omnichannel using the authenticated merchant and tenant. This feature is in testing and has not been released to production.

## Request rules

* Use the existing `Authorization: Bearer <access_token>` header. Operator identity is obtained from the authenticated merchant; request-body operator fields are not accepted as the audit identity.
* Use valid tenant warehouse and Master SKU values. Obtain `shippingAddress.districtId` from `/api/region/list`.
* `shippingAddress.postal`, `courier`, and `paymentMethod` are required by final order validation.
* Currency is IDR. Send whole-number quantities and amounts where possible. Quantity, paid unit price, shipping fee, and other fees are rounded to integers using HALF_UP.
* Paid unit price cannot exceed the current Master selling price. Item subtotal is the sum of paid unit price × quantity. Order discount cannot exceed that subtotal. Total = subtotal − order discount + shipping fee + other fees.
* Available stock is checked in the selected warehouse, including combined component demand from bundles and standalone items. Reservation and deduction are asynchronous; submission validation is not an immediate stock reservation guarantee.
* The trimmed `clientRefNo` becomes the order number. Repeated references return `DUPLICATE_CLIENT_REF`, rather than returning the existing order.
* Customer tags are applied asynchronously. An existing tag name is reused. Tag assignment is skipped when the customer already has 3 tags, or when a new tag is needed and the tenant already has 15 tags; order creation still succeeds.
* For subsequent delivery confirmation, use the existing `/api/order/confirmDelivery` endpoint.

## Request example

Resource identifiers below are placeholders or demo values and must be replaced with valid values for the tenant.

``` json
{"clientRefNo":"MANUAL-DEMO-001","customer":{"name":"Demo Customer","phone":"+6281234567890"},"shippingAddress":{"districtId":"<districtId from /api/region/list>","addressDetail":"Demo address","postal":"12345"},"warehouseId":123,"items":[{"masterSku":"DEMO-SKU","quantity":1}],"courier":"Custom courier","paymentMethod":"Bank Payment/Transfer","markOrderAsCompleted":false}
```

## Response example

``` json
{"code":"0","msg":null,"data":{"orderId":123456789,"displayedOrderSn":"MANUAL-DEMO-001"},"success":true}
```

## Errors

Business, authentication, and rate-limit errors use HTTP 200 with a non-zero `code`. Unexpected server exceptions use HTTP 500 with `SERVER_ERROR`. Always inspect `code`.

| code | Meaning |
| ---- | ------- |
| INVALID_PARAMETER | Missing, malformed, out-of-range, or invalid warehouse/product parameters |
| INVALID_TOKEN | Invalid, expired, or revoked access token |
| LIMIT_REQUEST | Existing request rate limit exceeded |
| DUPLICATE\_CLIENT\_REF | Reference number already exists within the tenant |
| INVALID_REGION | Invalid shipping district |
| INSUFFICIENT_STOCK | Insufficient available stock in the selected warehouse |
| SERVER_ERROR | Downstream service unavailable or other server error |

## Headers

- `Authorization` string, required

## Request body

- object
  - `clientRefNo` string, required: Your order reference. Trimmed length: 1–60 characters, without control characters. Must be unique among existing order numbers within the tenant.
  - `customer` object, required
    - `name` string, required: Required customer name; trimmed length at most 100 characters.
    - `phone` string, required: Required valid phone number; validated and normalized by the customer phone rules. Input length at most 255 characters.
    - `email` string: Optional valid email address; trimmed length at most 100 characters.
    - `tag` string: Optional single customer tag; trimmed length at most 15 characters, without control characters. Blank values are ignored.
  - `shippingAddress` object, required
    - `districtId` string, required: A valid Indonesian district ID returned by GET /api/region/list.
    - `addressDetail` string, required: Required detailed address; trimmed length at most 500 characters.
    - `postal` string, required: Required postal code; trimmed length at most 30 characters.
  - `warehouseId` integer, required: An active (not archived) Master warehouse ID belonging to the authenticated tenant.
  - `items` object[], required: Non-empty product list. Duplicate Master SKU codes are not allowed. Product details are resolved by the server.
    - `masterSku` string, required: Master SKU code, not an internal SKU ID. Trimmed length at most 255 characters.
    - `quantity` number, required: Quantity from 1 to 999999. Rounded to a whole number using HALF_UP; send an integer to avoid rounding.
    - `paidPrice` number: Optional paid unit price in IDR; defaults to the current Master selling price and cannot exceed it. Rounded to a whole number using HALF_UP.
  - `discount` object: Optional order-level discount. Supply both type and value when applying a discount.
    - `type` 'fixed' | 'percent': fixed: fixed amount in IDR; percent: percentage. Case and surrounding whitespace are ignored.
    - `value` number: Non-negative discount value. Percentage cannot exceed 100; the calculated discount cannot exceed the item subtotal.
  - `shippingFee` number: Shipping fee in IDR. Defaults to 0; rounded to a whole number using HALF_UP.
  - `otherFee` number: Other fees in IDR. Defaults to 0; rounded to a whole number using HALF_UP.
  - `courier` string, required: Required courier name, trimmed, at most 100 characters, without control characters. Custom names are supported.
  - `shipmentNo` string: Optional tracking number; trimmed length at most 255 characters.
  - `paymentMethod` string, required: Required payment method, trimmed, at most 50 characters, without control characters. Custom values are supported. COD is case-insensitive.
  - `sellerNotes` string: Optional seller notes; trimmed length at most 200 characters.
  - `markOrderAsCompleted` boolean, nullable: True creates a completed order. Omitted, null, or false creates a ready-to-ship order.

## Response `200`

successful operation

- object
  - `code` '0' | 'INVALID_PARAMETER' | 'INVALID_TOKEN' | 'LIMIT_REQUEST' | 'DUPLICATE_CLIENT_REF' | 'INVALID_REGION' | 'INSUFFICIENT_STOCK' | 'SERVER_ERROR', required: Business result code. 0 indicates success; other values indicate an error.
  - `msg` string, nullable: Result message; normally null on success.
  - `data` object, nullable: Response data on success; null on failure.
    - `orderId` integer, required: Internal order ID (Java Long). Clients must preserve 64-bit integer precision.
    - `displayedOrderSn` string, required: Final displayed order number, equal to the trimmed clientRefNo.
  - `success` boolean, required: True when code equals 0.

## Changes

- **2026-09-15** `716fec5542e1`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/desty/apis/desty-omni-openapi-2026-6-26/changes/api/order/manual/create/post.md)

---

[API](https://skmtc.dev/desty/apis/desty-omni-openapi-2026-6-26.md) - [All operations](https://skmtc.dev/desty/apis/desty-omni-openapi-2026-6-26/llms.txt) - [OpenAPI document](https://skmtc.dev/desty/apis/desty-omni-openapi-2026-6-26/revisions/4946760fb77d?raw)
