Edara API v3: Sales Returns
Read the guide first: authentication, paging, errors, rate limits and the shared PagedResult, BatchResult and *Reference shapes.
GET /v3/sales-returns: Gets a sales return by code.GET /v3/sales-returns/returnable: Gets the return proposal for an order.POST /v3/sales-returns: Creates a sales return by referencing an existing sales order or issue offering, with line details resolved from that document.
Endpoints
GET /v3/sales-returns: Gets a sales return by code.
Operation GetSalesReturnByCode · permission read:sales-return
codeis required.
Query string
| field | type | required | description |
|---|---|---|---|
code |
string |
yes | The sales return code. |
Responses: OK SalesReturnResponse: The sales return.
Notes
codeis trimmed and must start with "SR-", which is case-sensitive. An emptycodeor one with another prefix returns400.- The lookup is an exact match on
code. A return that does not exist, or one that has no lines, returns404. - Related records such as the customer, sales person, warehouse, store, currency, stock items, taxes, units of measure and accounts come back as reference objects. If one cannot be resolved, its reference contains only
id.
GET /v3/sales-returns/returnable: Gets the return proposal for an order.
Operation GetReturnableSalesReturn · permission read:sales-return
Query string
| field | type | required | description |
|---|---|---|---|
code |
string |
yes | Required. Sales-order code, issue-offering code, or a reference number that resolves to one. |
Responses: OK ReturnableSalesReturnResponse: The return proposal.
Business errors (HTTP 409, match on errorCode):
OrderHasNoIssuedItems: The order has no issued items to return (SalesReturnEligibilityLogic.FindReturnSource/ListReturnableLines).OrderCompletelyReturned: Every issued line on the order has already been returned in full (SalesReturnEligibilityLogic.ClassifyEmptyResult).SalesPersonNotPermitted: The order's salesperson is not one the current user may see (SalesReturnEligibilityLogic.IsSalesPersonPermitted).
Notes
codeis trimmed. A value that contains "SO-" is read as a sales order code, and a value that contains "IO-" is read as an issue offering code.- Any other value is read as a paper number. If several sales documents share that paper number, the one with the earliest date is used.
- If no order is found, you get
404. - For a sales order code, the proposal covers the lines of every issue offering related to that order. For an issue offering code, it covers only that issue offering.
- Only lines that still have something to return are listed, and the quantity shown is the issued quantity minus what was already returned. Archived issue offerings are included.
- Service lines are included only when the order has a related sales invoice for services, and only for service lines that are issued and still have a quantity to return. An order with only service items is handled entirely this way.
- When nothing is returnable, the
errorCodesays why.OrderHasNoIssuedItemsmeans nothing has been issued for the sales order yet, andOrderCompletelyReturnedmeans everything issued has already been returned. - For an issue offering code with nothing left to return, you get
OrderCompletelyReturnedif the issue offering exists and404if it does not. - The tax settings, currency, exchange rate and sales person of the proposal come from the original sales order. An issue offering that has no sales order gets no tax.
- If the order has a sales person that your user is not permitted to use, the request fails with
409anderrorCodeSalesPersonNotPermitted. - Each line gets a unit discount taken from the original order line's item discount. When the original order's prices included tax, the proposed price has the tax removed.
- A line that comes from a replacement issue offering points to the original issue offering line. The customer is taken from the first line.
cashAmount,notesReceivableAmountandonAccountAmountare only a proposal. The refund is proposed as cash if the order had any cash payment, otherwise as notes receivable if the order had any, otherwise on account.- Amounts and quantities are rounded to the number of decimal places in the organization's settings, 4 by default. This can differ between organizations.
- If the sales order has no currency, the organization's system currency is returned.
POST /v3/sales-returns: Creates a sales return by referencing an existing sales order or issue offering, with line details resolved from that document.
Operation CreateSalesReturn · permission create:sales-return
Body: CreateSalesReturnRequest
| field | type | default | validation | description |
|---|---|---|---|---|
warehouseId |
int? |
NotNull() .GreaterThan(0) | Receiving warehouse id. Required. | |
sourceDocumentCode |
string |
NotEmpty() .Must(code => code != null && (code.IndexOf("SO-", StringComparison.OrdinalIgnoreCase) >= 0 || code.IndexOf("IO-", StringComparison.OrdinalIgnoreCase) >= 0)) | A Sales Order code ("SO-...") or Issue Offering code ("IO-..."). Required. | |
documentDate |
DateTime? |
NotNull() | Document date (ISO 8601). Required. | |
notes |
string |
Free-text notes. | ||
cashAmount |
decimal? |
Cash amount returned to the customer. | ||
cashAccountId |
int? |
Cash/bank account id. Required only when the calling user's permissions require an automatic cash-out and CashAmount is greater than zero. |
||
exchangeRate |
decimal? |
GreaterThan(0) .When(x => x.ExchangeRate.HasValue) | Exchange rate to system currency. Omitted means the referenced document's own exchange rate. | |
returnDiscount |
decimal? |
GreaterThanOrEqualTo(0) .When(x => x.ReturnDiscount.HasValue) | Order-level discount amount. | |
sourceDocumentDetails |
List<CreateSalesReturnDetailRequest> |
each: NotNull() .SetValidator(new CreateSalesReturnDetailRequestValidator()) .When(x => x.SourceDocumentDetails != null) | Lines to return. Omitted entirely means every returnable item on the referenced document. |
Responses: Created SalesReturnResponse: Sales return created.
Business errors (HTTP 409, match on errorCode):
SourceLineNotFound: A sourceSalesOrderDetailId/sourceWorkOrderDetailId in sourceDocumentDetails doesn't match any returnable line on the referenced document, or a sourceSalesOrderDetailId was given alone while sourceDocumentCode is an issue offering (SalesReturnUnifiedLogic.FindUnmatchedSelectors/RowMatchesSelector).DuplicateSourceLineId: The same source line was referenced more than once in sourceDocumentDetails (SalesReturnUnifiedLogic.FindDuplicateSelectors).SourceDetailTypeMismatch: sourceSalesOrderDetailId was given alone but resolves to a stock item, not a service item; supply sourceWorkOrderDetailId instead (SalesReturnUnifiedLogic.ValidateSelectorAgainstRow).SourceDetailLinkageMismatch: Both sourceSalesOrderDetailId and sourceWorkOrderDetailId were given but don't refer to the same line (SalesReturnUnifiedLogic.ValidateSelectorAgainstRow).ReturnDiscountMismatch: The provided returnDiscount doesn't match the computed sum of the resolved lines' own discounts (SalesReturnUnifiedLogic.CreateSalesReturnFromSource).OverLimitReturnedQuantity: The requested quantity for a line exceeds that line's remaining returnable balance (SalesReturnUnifiedLogic.ValidateReturnableQuantities).NoSelectedTreasury: cashAmount is greater than zero and the calling user's permissions require an automatic cash-out, but cashAccountId wasn't supplied (SalesReturnUnifiedLogic.ValidateTreasuryForAutoCash).TreasuryAccountTypeInvalid: The account referenced by cashAccountId is not of type Cash or Bank (SalesReturnUnifiedLogic.ValidateTreasuryForAutoCash).TreasuryNotPermitted: The calling user has no Cash Account / Bank Account permission on the account referenced by cashAccountId (SalesReturnUnifiedLogic.ValidateTreasuryForAutoCash).CustomerHaveNoRelatedAccount: The selected customer has no related GL account; raised when the journal entry for the return is created (AccDocumentLogic).RelatedSalesOrderCancelled: The source sales order is already cancelled, raised when the journal entry for an automatic cash-out or credit note is created for the return (AccDocumentLogic.InsertAccDocument).SalesReturnAlreadyReceived: The receiving work order linked to this sales return has already been issued, so it cannot be processed again (WorkOrder).ExchangeRateDecimalsExceedLimit: The exchange rate exceeds the allowed decimal precision.EdaraBusinessError: A legacy validation rule inside the shared sales-document insert pipeline rejected the request, e.g. zero/duplicated items, price below cost, or a discount exceeding the total (SalesDocumentLogic.InsertSalesDocument).
Notes
- The source document and its returnable lines are worked out the same way as in GET /v3/sales-returns/returnable.
- A source that is not found returns
404. A source with nothing issued or nothing left to return gives409witherrorCodeOrderHasNoIssuedItemsorOrderCompletelyReturned. - If you omit
sourceDocumentDetailsor send it empty, every returnable line is returned at its full remaining quantity and its source price. - When you send
sourceDocumentDetails, each entry must match exactly one returnable line. A stock item line matches onsourceWorkOrderDetailIdor onsourceSalesOrderDetailId, and a service line matches onsourceSalesOrderDetailIdonly. - When the source is an issue offering code, an entry that has only
sourceSalesOrderDetailIdnever matches. - Sending the same line twice gives
DuplicateSourceLineId. An entry that matches no returnable line givesSourceLineNotFound, and the error names the id. - An entry with a badly formed combination of ids gives
SourceDetailTypeMismatchorSourceDetailLinkageMismatch. - Per line,
quantityandpricedefault to the remaining quantity and the source price.taxRateandunitDiscountalways come from the source document, andtaxIdandwithholdingTaxIdcome from the original sales order line. - Serial numbers are never saved on a return created with this endpoint.
returnDiscountis a check value, not an extra discount. If you send it, it must equal the total of the line discounts to 4 decimal places.cashAmountdefaults to 0.onAccountAmountis the rounded net total minuscashAmount, and the notes receivable amount is always 0.- The customer comes from the first returned line. The sales person, the tax settings and the currency are copied from the original sales order.
- If that currency is the organization's system currency,
exchangeRateis always 1 and the value you send is ignored. Otherwise yourexchangeRateis used, then the sales order's rate, then 1. - An
exchangeRatewith more than 4 decimal places is rejected withExchangeRateDecimalsExceedLimit. - Organization settings decide whether the new return is approved automatically, issued automatically, and whether a related work order and cash payment are created with it. Each one applies only when the setting is on and your user is on the organization's list of users for automatic related documents.
- Other organization settings also change the outcome: requiring a sales person, requiring a cost center, allowing a zero total, allowing a zero price, and limiting the return quantity by other pending returns. Results differ between organizations, so code defensively.
- Checks run in this order: header, lines, treasury, quantities, then customer.
- Header checks give
SalesPersonRequired,CostCenterRequired,NegativeNetTotal,CashExceedsTotal,DateBeforeRelatedSalesOrderwhendocumentDateis earlier than the sales order date, orZeroTotalNotAllowed. - This endpoint cannot set a cost center. If the organization requires a cost center on sales returns, every create fails with
CostCenterRequired. - Line checks give
ZeroQuantity,ZeroPrice, orServiceOnlyForMixedOrderwhen you select only the service lines of an order that also has stock items. - Treasury checks run only when an automatic cash payment applies and
cashAmountis above 0. They giveNoSelectedTreasury,TreasuryHasNoAlias,TreasuryAccountTypeInvalidorTreasuryNotPermitted. - For each stock item line, the quantity, converted to the issue offering's unit of measure, cannot be more than the issued quantity minus what was already returned. Otherwise you get
OverLimitReturnedQuantity. - Where the organization setting is on, quantities on other returns that are not yet issued are also subtracted from what you can return.
- A return whose customer has no name fails with
SecondPartyMandatory. - The new return is linked to the source document, and the sales order's payment status is recalculated.
- When an automatic cash payment applies and
cashAmountis above 0, a cash-out journal entry is posted that debits the customer and credits the treasury. - When an automatic work order applies, an order with stock items gets a receive-return work order that adds the stock back, and the return is marked as issued with the status
Returned. An order with only services gets a credit note invoice instead. - Without the automatic work order, no stock moves and no journal entry is posted. The return is saved as a pending document.
- The response is the saved return read back after the create, the same as GET /v3/sales-returns gives for its code.
Types
AccountReference
Lightweight account reference (id + code + name).
| field | type | description |
|---|---|---|
id |
int |
The account id. |
code |
string |
The account code. |
name |
string |
The account name. |
CreateSalesReturnDetailRequest
One line of a sales return, identified by the exact line it returns against on the referenced sales order or issue offering.
| field | type | validation | description |
|---|---|---|---|
sourceSalesOrderDetailId |
int? |
Detail id on the referenced sales order. At least one of this or SourceWorkOrderDetailId is required; supplying both is validated against the resolved line. Alone, it must resolve to a service item. |
|
sourceWorkOrderDetailId |
int? |
Detail id on the referenced issue offering. At least one of this or SourceSalesOrderDetailId is required; supplying both is validated against the resolved line. |
|
quantity |
decimal? |
GreaterThan(0) .When(x => x.Quantity.HasValue) | Quantity to return. Omitted means the line's full remaining returnable quantity. |
price |
decimal? |
GreaterThanOrEqualTo(0) .When(x => x.Price.HasValue) | Line price. Omitted means the referenced document's own price for this line. |
CurrencyReference
Lightweight currency reference (id + ISO code + name).
| field | type | description |
|---|---|---|
id |
int |
The currency id. |
code |
string |
The ISO 4217 currency code. |
name |
string |
The currency name. |
CustomerReference
Lightweight customer reference (id + code + name).
| field | type | description |
|---|---|---|
id |
int |
The customer id. |
code |
string |
The customer code. |
name |
string |
The customer name. |
DocumentType
Document type codes shared across sales, purchase, and warehouse domains.
Values (sent/returned as the name): RS, RR, RT, IO, IR, IT, TR, CI, CO, JE, SI, PI, CN, DN, NR, NP, SO, SR, RecSO, PO, PR, OB, RMA
ReturnableSalesReturnLineResponse
A single returnable line within a ReturnableSalesReturnResponse.
| field | type | description |
|---|---|---|
sourceSalesOrderDetailId |
int? |
Detail id on the originating sales order, when one exists. |
sourceWorkOrderDetailId |
int? |
Detail id on the originating work order (IO), when one exists. |
relatedWorkOrderCode |
string |
The IO this line was actually delivered on and must be submitted with this line when creating a return. A single order can be fulfilled by more than one IO - null for pure service lines, which have none. |
stockItem |
StockItemReference |
The returned stock item. Null for service lines. |
serviceItem |
ServiceItemReference |
The returned service item. Null for goods lines. |
quantity |
decimal |
Quantity still returnable (delivered minus already returned). |
unitOfMeasure |
UnitOfMeasureReference |
Unit of measure the returnable quantity is expressed in. |
unitPrice |
decimal |
Unit price before discount/tax, as originally sold. |
price |
decimal |
Unit price actually used for Total - tax-exclusive, in settlement currency. |
taxRate |
decimal |
Tax rate from the original sale. |
unitDiscount |
decimal |
Discount per unit. |
total |
decimal |
Quantity × Price. |
discount |
decimal |
Quantity × UnitDiscount. |
lineTax |
decimal |
Tax amount for this line. |
batchNumber |
string |
Batch number, when batch tracking is in use. |
expiryDate |
DateTime? |
Batch expiry date. |
ReturnableSalesReturnResponse
The computed return proposal for an order: everything a caller needs to build a POST /v3/sales-returns request for a full or partial return.
| field | type | description |
|---|---|---|
customer |
CustomerReference |
Customer on the original order, locked for the return. |
salesPerson |
SalesPersonReference |
Salesperson on the original order, when one is set. |
currency |
CurrencyReference |
Currency the original order was placed in. The system currency when the order didn't set one explicitly. |
exchangeRate |
decimal |
Exchange rate to system currency. Needed to submit POST /v3/sales-returns for a non-system-currency order. |
grossTotal |
decimal |
Gross total, before discounts and taxes. |
subTotal |
decimal |
Sub-total after item discounts, before taxes. |
netTotal |
decimal |
Net total after discounts and taxes. |
salesReturnDiscounts |
decimal |
Sum of item-level discounts. |
taxable |
bool |
Whether tax applies to this return. |
applyTaxAfterDiscount |
bool |
Whether tax was calculated on the discounted amount. |
tax |
decimal |
Total tax amount. |
cashAmount |
decimal |
Cash amount the refund defaults to. |
onAccountAmount |
decimal |
Amount the refund defaults to crediting to the customer account. |
notesReceivableAmount |
decimal |
Amount the refund defaults to as a note receivable. |
lines |
List<ReturnableSalesReturnLineResponse> |
Returnable lines. |
SalesPersonReference
Lightweight sales-person reference (id + code + name).
| field | type | description |
|---|---|---|
id |
int |
The sales-person id. |
code |
string |
The sales-person code. |
name |
string |
The sales-person name. |
SalesReturnDiscountType
Discount calculation mode for sales-return line items.
Values (sent/returned as the name): Value=0 (The discount is treated as a fixed value.), Percentage=1 (The discount is treated as a percentage of the line total.)
SalesReturnInstallmentResponse
Response describing a sales-return installment.
| field | type | description |
|---|---|---|
amount |
decimal? |
Installment amount. |
daysLimit |
int? |
Days from document date until due. |
dueDate |
DateTime? |
Due date. |
account |
AccountReference |
Account collecting or paying the installment. |
paymentType |
SalesReturnPaymentType? |
Payment method. |
SalesReturnItemResponse
Response describing a sales-return line item.
| field | type | description |
|---|---|---|
id |
int? |
Line identifier. |
quantity |
decimal? |
Quantity returned. |
issuedQuantity |
decimal? |
Quantity already received back. |
unitPrice |
decimal? |
Unit price (pre-tax, pre-discount). |
price |
decimal? |
Line price as charged on the original sale (post-discount, pre-tax). |
taxRate |
decimal? |
Tax rate from the original sale. |
tax |
TaxReference |
Tax applied to the line. |
itemDiscount |
decimal? |
Item discount value. |
itemDiscountType |
SalesReturnDiscountType? |
Item discount type (value or percentage). |
warehouse |
WarehouseReference |
Receiving warehouse. |
bundleId |
int? |
Bundle id, when applicable. |
stockItem |
StockItemReference |
Returned stock item. |
unitOfMeasure |
UnitOfMeasureReference |
Unit of measure. |
batchNumber |
string |
Batch number. |
expiryDate |
DateTime? |
Batch expiry date. |
comments |
string |
Free-text line comments. |
returnedQuantity |
decimal? |
Quantity previously returned against the original sale. |
bundleQuantity |
decimal? |
Bundle component quantity, when applicable. |
relatedSerials |
List<string> |
Returned serial numbers, for serialized items. |
SalesReturnOrderStatus
Sales-return lifecycle states.
Values (sent/returned as the name): Cancelled=0 (The sales return is cancelled.), Confirmed=1 (The sales return is confirmed.), Pending=2 (The sales return is pending processing.), Processing=3 (The sales return is being processed.), OutForDelivery=4 (The sales return is out for delivery.), Shipped=5 (The sales return has been shipped.), Returned=6 (The sales return was returned by the customer or logistics flow.)
SalesReturnPaymentStatus
Sales-return payment states.
Values (sent/returned as the name): Unpaid=0 (The sales return is unpaid.), PartiallyPaid=1 (The sales return is partially paid.), Paid=2 (The sales return is fully paid.)
SalesReturnPaymentType
Sales-return installment payment methods.
Values (sent/returned as the name): Cash=0 (Payment is collected in cash.), CashOnDelivery=1 (Payment is collected cash on delivery.), OnAccount=2 (Payment is posted on account.)
SalesReturnResponse
Response describing a sales return.
| field | type | description |
|---|---|---|
id |
int |
Sales-return identifier. |
documentCode |
string |
Document code (e.g. "SR-2026-00001"). |
orderStatus |
SalesReturnOrderStatus? |
Lifecycle status. |
documentType |
DocumentType? |
Document type. Always SR. |
paperNumber |
string |
Paper / reference number. |
runSheetId |
string |
Run-sheet identifier. |
customer |
CustomerReference |
Customer reference. |
salesPerson |
SalesPersonReference |
Sales person reference. |
warehouse |
WarehouseReference |
Receiving warehouse. |
salesStore |
SalesStoreReference |
Sales store / POS location. |
shippmentCost |
decimal? |
Shipping cost reimbursed. |
documentDate |
DateTime? |
Document date. |
shippingDate |
DateTime? |
Expected shipping date. |
grossTotal |
decimal? |
Gross total, before discounts and taxes. |
subTotal |
decimal? |
Sub-total after item discounts, before order discount and taxes. |
netTotal |
decimal? |
Net total after discounts and taxes. |
totalItemsDiscounts |
decimal? |
Sum of item-level discounts. |
discount |
decimal? |
Order-level discount amount. |
discountRate |
decimal? |
Order-level discount percentage. |
taxable |
bool? |
Whether tax was applied. |
applyTaxAfterDiscount |
bool? |
Whether tax was calculated on the discounted amount. |
tax |
decimal? |
Total tax amount. |
cashAmount |
decimal? |
Cash amount returned. |
onAccountAmount |
decimal? |
Amount credited to the customer account. |
cashPaid |
decimal? |
Actual cash paid back. |
currency |
CurrencyReference |
Settlement currency. |
exchangeRate |
decimal? |
Exchange rate to system currency. |
channel |
string |
Sales channel. |
notes |
string |
Free-text notes. |
externalId |
string |
External system identifier. |
relatedWorkOrderCode |
string |
Related issue-offering work-order code. |
relatedWorkOrderValue |
decimal? |
Value on the related issue-offering work order. |
tags |
List<string> |
Tags. |
relatedSalesReturnCodes |
List<string> |
Related sales-return codes. |
relatedSalesOrderCodes |
List<string> |
Related sales-order codes. |
paymentInformation |
Dictionary<string,decimal> |
Payment breakdown keyed by method. |
salesOrderDetails |
List<SalesReturnItemResponse> |
Return lines. |
salesOrderInstallments |
List<SalesReturnInstallmentResponse> |
Installments. |
documentNumber |
string |
Sequential document number within the SR series. |
fulfillmentDate |
DateTime? |
Fulfillment date. |
deviceSerial |
string |
POS device serial. |
addressId |
int? |
Customer address id. |
addressDescription |
string |
Free-text delivery address description. |
paymentStatus |
SalesReturnPaymentStatus? |
Payment status. |
otherCreditAmount |
decimal? |
Amount settled via other credit instruments. |
isApproved |
bool |
Whether the return has been approved. |
isIssued |
bool |
Whether the return has been issued (stock received). |
requireAutoWorkorder |
bool |
Whether an auto-generated receiving work order is required. |
SalesStoreReference
Lightweight sales-store reference (id + code + name).
| field | type | description |
|---|---|---|
id |
int |
The sales-store id. |
code |
string |
The sales-store code. |
name |
string |
The sales-store name. |
ServiceItemReference
Lightweight reference to a service item.
| field | type | description |
|---|---|---|
id |
int |
Service-item identifier. |
code |
string |
Service-item code. |
description |
string |
Service-item description. |
StockItemReference
Lightweight stock-item reference (id + code + description).
| field | type | description |
|---|---|---|
id |
int |
The stock-item id. |
code |
string |
The stock-item code. |
description |
string |
The stock-item description. |
TaxReference
Lightweight tax reference (id + name + rate).
| field | type | description |
|---|---|---|
id |
int |
The tax id. |
name |
string |
The tax name. |
rate |
decimal |
The tax rate as a percentage. |
UnitOfMeasureReference
Lightweight unit-of-measure reference (id + name).
| field | type | description |
|---|---|---|
id |
int |
The unit-of-measure id. |
name |
string |
The unit-of-measure name. |
WarehouseReference
Lightweight warehouse reference (id + code + name).
| field | type | description |
|---|---|---|
id |
int |
The warehouse id. |
code |
string |
The warehouse code. |
name |
string |
The warehouse name. |